Bug:Fix file validation issue
[vnfsdk/refrepo.git] / vnfmarket / src / main / webapp / vnfmarket / node_modules / ws / lib / Sender.js
1 /*!
2  * ws: a node.js websocket client
3  * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
4  * MIT Licensed
5  */
6
7 var events = require('events')
8   , util = require('util')
9   , EventEmitter = events.EventEmitter
10   , ErrorCodes = require('./ErrorCodes')
11   , bufferUtil = require('./BufferUtil').BufferUtil;
12
13 /**
14  * HyBi Sender implementation
15  */
16
17 function Sender(socket) {
18   this._socket = socket;
19   this.firstFragment = true;
20 }
21
22 /**
23  * Inherits from EventEmitter.
24  */
25
26 util.inherits(Sender, events.EventEmitter);
27
28 /**
29  * Sends a close instruction to the remote party.
30  *
31  * @api public
32  */
33
34 Sender.prototype.close = function(code, data, mask) {
35   if (typeof code !== 'undefined') {
36     if (typeof code !== 'number' ||
37       !ErrorCodes.isValidErrorCode(code)) throw new Error('first argument must be a valid error code number');
38   }
39   code = code || 1000;
40   var dataBuffer = new Buffer(2 + (data ? Buffer.byteLength(data) : 0));
41   writeUInt16BE.call(dataBuffer, code, 0);
42   if (dataBuffer.length > 2) dataBuffer.write(data, 2);
43   this.frameAndSend(0x8, dataBuffer, true, mask);
44 };
45
46 /**
47  * Sends a ping message to the remote party.
48  *
49  * @api public
50  */
51
52 Sender.prototype.ping = function(data, options) {
53   var mask = options && options.mask;
54   this.frameAndSend(0x9, data || '', true, mask);
55 };
56
57 /**
58  * Sends a pong message to the remote party.
59  *
60  * @api public
61  */
62
63 Sender.prototype.pong = function(data, options) {
64   var mask = options && options.mask;
65   this.frameAndSend(0xa, data || '', true, mask);
66 };
67
68 /**
69  * Sends text or binary data to the remote party.
70  *
71  * @api public
72  */
73
74 Sender.prototype.send = function(data, options, cb) {
75   var finalFragment = options && options.fin === false ? false : true;
76   var mask = options && options.mask;
77   var opcode = options && options.binary ? 2 : 1;
78   if (this.firstFragment === false) opcode = 0;
79   else this.firstFragment = false;
80   if (finalFragment) this.firstFragment = true
81   this.frameAndSend(opcode, data, finalFragment, mask, cb);
82 };
83
84 /**
85  * Frames and sends a piece of data according to the HyBi WebSocket protocol.
86  *
87  * @api private
88  */
89
90 Sender.prototype.frameAndSend = function(opcode, data, finalFragment, maskData, cb) {
91   var canModifyData = false;
92
93   if (!data) {
94     try {
95       this._socket.write(new Buffer([opcode | (finalFragment ? 0x80 : 0), 0 | (maskData ? 0x80 : 0)].concat(maskData ? [0, 0, 0, 0] : [])), 'binary', cb);
96     }
97     catch (e) {
98       if (typeof cb == 'function') cb(e);
99       else this.emit('error', e);
100     }
101     return;
102   }
103
104   if (!Buffer.isBuffer(data)) {
105     canModifyData = true;
106     if (data && (typeof data.byteLength !== 'undefined' || typeof data.buffer !== 'undefined')) {
107       data = getArrayBuffer(data);
108     } else {
109       data = new Buffer(data);
110     }
111   }
112
113   var dataLength = data.length
114     , dataOffset = maskData ? 6 : 2
115     , secondByte = dataLength;
116
117   if (dataLength >= 65536) {
118     dataOffset += 8;
119     secondByte = 127;
120   }
121   else if (dataLength > 125) {
122     dataOffset += 2;
123     secondByte = 126;
124   }
125
126   var mergeBuffers = dataLength < 32768 || (maskData && !canModifyData);
127   var totalLength = mergeBuffers ? dataLength + dataOffset : dataOffset;
128   var outputBuffer = new Buffer(totalLength);
129   outputBuffer[0] = finalFragment ? opcode | 0x80 : opcode;
130
131   switch (secondByte) {
132     case 126:
133       writeUInt16BE.call(outputBuffer, dataLength, 2);
134       break;
135     case 127:
136       writeUInt32BE.call(outputBuffer, 0, 2);
137       writeUInt32BE.call(outputBuffer, dataLength, 6);
138   }
139
140   if (maskData) {
141     outputBuffer[1] = secondByte | 0x80;
142     var mask = this._randomMask || (this._randomMask = getRandomMask());
143     outputBuffer[dataOffset - 4] = mask[0];
144     outputBuffer[dataOffset - 3] = mask[1];
145     outputBuffer[dataOffset - 2] = mask[2];
146     outputBuffer[dataOffset - 1] = mask[3];
147     if (mergeBuffers) {
148       bufferUtil.mask(data, mask, outputBuffer, dataOffset, dataLength);
149       try {
150         this._socket.write(outputBuffer, 'binary', cb);
151       }
152       catch (e) {
153         if (typeof cb == 'function') cb(e);
154         else this.emit('error', e);
155       }
156     }
157     else {
158       bufferUtil.mask(data, mask, data, 0, dataLength);
159       try {
160         this._socket.write(outputBuffer, 'binary');
161         this._socket.write(data, 'binary', cb);
162       }
163       catch (e) {
164         if (typeof cb == 'function') cb(e);
165         else this.emit('error', e);
166       }
167     }
168   }
169   else {
170     outputBuffer[1] = secondByte;
171     if (mergeBuffers) {
172       data.copy(outputBuffer, dataOffset);
173       try {
174         this._socket.write(outputBuffer, 'binary', cb);
175       }
176       catch (e) {
177         if (typeof cb == 'function') cb(e);
178         else this.emit('error', e);
179       }
180     }
181     else {
182       try {
183         this._socket.write(outputBuffer, 'binary');
184         this._socket.write(data, 'binary', cb);
185       }
186       catch (e) {
187         if (typeof cb == 'function') cb(e);
188         else this.emit('error', e);
189       }
190     }
191   }
192 };
193
194 module.exports = Sender;
195
196 function writeUInt16BE(value, offset) {
197   this[offset] = (value & 0xff00)>>8;
198   this[offset+1] = value & 0xff;
199 }
200
201 function writeUInt32BE(value, offset) {
202   this[offset] = (value & 0xff000000)>>24;
203   this[offset+1] = (value & 0xff0000)>>16;
204   this[offset+2] = (value & 0xff00)>>8;
205   this[offset+3] = value & 0xff;
206 }
207
208 function getArrayBuffer(data) {
209   // data is either an ArrayBuffer or ArrayBufferView.
210   var array = new Uint8Array(data.buffer || data)
211     , l = data.byteLength || data.length
212     , o = data.byteOffset || 0
213     , buffer = new Buffer(l);
214   for (var i = 0; i < l; ++i) {
215     buffer[i] = array[o+i];
216   }
217   return buffer;
218 }
219
220 function getRandomMask() {
221   return new Buffer([
222     ~~(Math.random() * 255),
223     ~~(Math.random() * 255),
224     ~~(Math.random() * 255),
225     ~~(Math.random() * 255)
226   ]);
227 }