1 /*!
2  * ws: a node.js websocket client
3  * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
4  * MIT Licensed
5  */
6 
7 #include <v8.h>
8 #include <node.h>
9 #include <node_buffer.h>
10 #include <node_object_wrap.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <wchar.h>
14 #include <stdio.h>
15 #include "nan.h"
16 
17 using namespace v8;
18 using namespace node;
19 
20 class BufferUtil : public ObjectWrap
21 {
22 public:
23 
Initialize(v8::Handle<v8::Object> target)24   static void Initialize(v8::Handle<v8::Object> target)
25   {
26     NanScope();
27     Local<FunctionTemplate> t = NanNew<FunctionTemplate>(New);
28     t->InstanceTemplate()->SetInternalFieldCount(1);
29     NODE_SET_METHOD(t, "unmask", BufferUtil::Unmask);
30     NODE_SET_METHOD(t, "mask", BufferUtil::Mask);
31     NODE_SET_METHOD(t, "merge", BufferUtil::Merge);
32     target->Set(NanSymbol("BufferUtil"), t->GetFunction());
33   }
34 
35 protected:
36 
NAN_METHOD(New)37   static NAN_METHOD(New)
38   {
39     NanScope();
40     BufferUtil* bufferUtil = new BufferUtil();
41     bufferUtil->Wrap(args.This());
42     NanReturnValue(args.This());
43   }
44 
NAN_METHOD(Merge)45   static NAN_METHOD(Merge)
46   {
47     NanScope();
48     Local<Object> bufferObj = args[0]->ToObject();
49     char* buffer = Buffer::Data(bufferObj);
50     Local<Array> array = Local<Array>::Cast(args[1]);
51     unsigned int arrayLength = array->Length();
52     size_t offset = 0;
53     unsigned int i;
54     for (i = 0; i < arrayLength; ++i) {
55       Local<Object> src = array->Get(i)->ToObject();
56       size_t length = Buffer::Length(src);
57       memcpy(buffer + offset, Buffer::Data(src), length);
58       offset += length;
59     }
60     NanReturnValue(NanTrue());
61   }
62 
NAN_METHOD(Unmask)63   static NAN_METHOD(Unmask)
64   {
65     NanScope();
66     Local<Object> buffer_obj = args[0]->ToObject();
67     size_t length = Buffer::Length(buffer_obj);
68     Local<Object> mask_obj = args[1]->ToObject();
69     unsigned int *mask = (unsigned int*)Buffer::Data(mask_obj);
70     unsigned int* from = (unsigned int*)Buffer::Data(buffer_obj);
71     size_t len32 = length / 4;
72     unsigned int i;
73     for (i = 0; i < len32; ++i) *(from + i) ^= *mask;
74     from += i;
75     switch (length % 4) {
76       case 3: *((unsigned char*)from+2) = *((unsigned char*)from+2) ^ ((unsigned char*)mask)[2];
77       case 2: *((unsigned char*)from+1) = *((unsigned char*)from+1) ^ ((unsigned char*)mask)[1];
78       case 1: *((unsigned char*)from  ) = *((unsigned char*)from  ) ^ ((unsigned char*)mask)[0];
79       case 0:;
80     }
81     NanReturnValue(NanTrue());
82   }
83 
NAN_METHOD(Mask)84   static NAN_METHOD(Mask)
85   {
86     NanScope();
87     Local<Object> buffer_obj = args[0]->ToObject();
88     Local<Object> mask_obj = args[1]->ToObject();
89     unsigned int *mask = (unsigned int*)Buffer::Data(mask_obj);
90     Local<Object> output_obj = args[2]->ToObject();
91     unsigned int dataOffset = args[3]->Int32Value();
92     unsigned int length = args[4]->Int32Value();
93     unsigned int* to = (unsigned int*)(Buffer::Data(output_obj) + dataOffset);
94     unsigned int* from = (unsigned int*)Buffer::Data(buffer_obj);
95     unsigned int len32 = length / 4;
96     unsigned int i;
97     for (i = 0; i < len32; ++i) *(to + i) = *(from + i) ^ *mask;
98     to += i;
99     from += i;
100     switch (length % 4) {
101       case 3: *((unsigned char*)to+2) = *((unsigned char*)from+2) ^ *((unsigned char*)mask+2);
102       case 2: *((unsigned char*)to+1) = *((unsigned char*)from+1) ^ *((unsigned char*)mask+1);
103       case 1: *((unsigned char*)to  ) = *((unsigned char*)from  ) ^ *((unsigned char*)mask);
104       case 0:;
105     }
106     NanReturnValue(NanTrue());
107   }
108 };
109 
init(Handle<Object> target)110 extern "C" void init (Handle<Object> target)
111 {
112   NanScope();
113   BufferUtil::Initialize(target);
114 }
115 
116 NODE_MODULE(bufferutil, init)
117 
118