foam-framework
Version:
MVC metaprogramming framework
160 lines (143 loc) • 4.62 kB
JavaScript
/**
* @license
* Copyright 2015 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
CLASS({
package: 'foam.node.ws',
name: 'Frame',
properties: [
['fin', 1],
['rsv1',0],
['rsv2',0],
['rsv3',0],
['opcode',1],
['mask',0],
'maskingKey',
'buffer',
['bufferPos', 0],
['needed', 0],
['framing', 'true'],
['finished', 'false'],
],
methods: [
function toData() {
this.length = this.buffer.length;
var headerSize = this.buffer.length > 65535 ? 10 :
(this.buffer.length > 125 ? 4 : 2);
var i = 0;
var buffer = new Buffer(this.buffer.length + headerSize);
// FIN = 1, RSV1-3 = 0
buffer.writeUInt8(
0x80 +
this.opcode, i++);
var length = this.length;
if ( length > 65535 ) {
buffer.writeUInt8(127, i++);
buffer.writeUInt8(length >> 56, i++)
buffer.writeUInt8(length >> 48, i++)
buffer.writeUInt8(length >> 40, i++)
buffer.writeUInt8(length >> 32, i++)
buffer.writeUInt8(length >> 24, i++)
buffer.writeUInt8(length >> 16, i++)
buffer.writeUInt8((length & 0xff00) >> 8, i++)
buffer.writeUInt8(length & 0xff, i++)
} else if ( length > 125 ) {
buffer.writeUInt8(126, i++);
buffer.writeUInt8((length & 0xff00) >> 8, i++)
buffer.writeUInt8(length & 0xff, i++)
} else {
buffer.writeUInt8(length & 0x7f, i++);
}
this.buffer.copy(buffer, i);
return buffer;
},
function onData(data, i) {
if ( this.framing ) {
var byte = data.readUInt8(i++);
this.opcode = byte & 0x0f;
this.fin = !! ( byte & 0x80 );
this.rsv1 = !! ( byte & 0x40 );
this.rsv2 = !! ( byte & 0x20 );
this.rsv3 = !! ( byte & 0x10 );
byte = data.readUInt8(i++);
this.mask = !! ( byte & 0x80 );
var length = byte & 0x7f;
if ( length == 126 ) {
length = 0;
byte = data.readUInt8(i++);
length += byte << 8;
byte = data.readUInt8(i++);
length += byte;
} else if ( length == 127 ) {
length = 0;
var tolarge = false;
byte = data.readUInt8(i++);
if ( byte !== 0 ) tolarge = true;
//length += byte << 56;
byte = data.readUInt8(i++);
if ( byte !== 0 ) tolarge = true;
//length += byte << 48;
byte = data.readUInt8(i++);
length += byte << 40;
byte = data.readUInt8(i++);
length += byte << 32;
byte = data.readUInt8(i++);
length += byte << 24;
byte = data.readUInt8(i++);
length += byte << 16;
byte = data.readUInt8(i++);
length += byte << 8;
byte = data.readUInt8(i++);
length += byte;
if ( tolarge ) {
console.error("Payload too large.");
this.socket.end();
return;
}
}
this.length = length;
this.buffer = new Buffer(this.length);
this.bufferPos = 0;
this.needed = this.length;
this.framing = false;
if ( this.mask ) {
this.masking_key = [];
byte = data.readUInt8(i++);
this.masking_key.push(byte);
byte = data.readUInt8(i++);
this.masking_key.push(byte);
byte = data.readUInt8(i++);
this.masking_key.push(byte);
byte = data.readUInt8(i++);
this.masking_key.push(byte);
}
}
var amount = Math.min(data.length - i, this.needed);
data.copy(this.buffer, this.bufferPos, i, i + amount);
if ( this.mask ) {
for ( var j = this.bufferPos ; j < this.bufferPos + amount; j++ ) {
this.buffer.writeUInt8(this.buffer.readUInt8(j) ^ this.masking_key[j % 4], j);
}
}
this.bufferPos += amount;
this.needed -= amount;
i += amount;
if ( this.needed == 0 ) {
this.finished = true;
}
return i;
}
]
});