Initial commit
[yaffs-website] / node_modules / websocket-driver / lib / websocket / driver / draft75.js
1 'use strict';
2
3 var Base = require('./base'),
4     util = require('util');
5
6 var Draft75 = function(request, url, options) {
7   Base.apply(this, arguments);
8   this._stage  = 0;
9   this.version = 'hixie-75';
10
11   this._headers.set('Upgrade', 'WebSocket');
12   this._headers.set('Connection', 'Upgrade');
13   this._headers.set('WebSocket-Origin', this._request.headers.origin);
14   this._headers.set('WebSocket-Location', this.url);
15 };
16 util.inherits(Draft75, Base);
17
18 var instance = {
19   close: function() {
20     if (this.readyState === 3) return false;
21     this.readyState = 3;
22     this.emit('close', new Base.CloseEvent(null, null));
23     return true;
24   },
25
26   parse: function(chunk) {
27     if (this.readyState > 1) return;
28
29     this._reader.put(chunk);
30
31     this._reader.eachByte(function(octet) {
32       var message;
33
34       switch (this._stage) {
35         case -1:
36           this._body.push(octet);
37           this._sendHandshakeBody();
38           break;
39
40         case 0:
41           this._parseLeadingByte(octet);
42           break;
43
44         case 1:
45           this._length = (octet & 0x7F) + 128 * this._length;
46
47           if (this._closing && this._length === 0) {
48             return this.close();
49           }
50           else if ((octet & 0x80) !== 0x80) {
51             if (this._length === 0) {
52               this._stage = 0;
53             }
54             else {
55               this._skipped = 0;
56               this._stage   = 2;
57             }
58           }
59           break;
60
61         case 2:
62           if (octet === 0xFF) {
63             this._stage = 0;
64             message = new Buffer(this._buffer).toString('utf8', 0, this._buffer.length);
65             this.emit('message', new Base.MessageEvent(message));
66           }
67           else {
68             if (this._length) {
69               this._skipped += 1;
70               if (this._skipped === this._length)
71                 this._stage = 0;
72             } else {
73               this._buffer.push(octet);
74               if (this._buffer.length > this._maxLength) return this.close();
75             }
76           }
77           break;
78       }
79     }, this);
80   },
81
82   frame: function(buffer) {
83     if (this.readyState === 0) return this._queue([buffer]);
84     if (this.readyState > 1) return false;
85
86     if (typeof buffer !== 'string') buffer = buffer.toString();
87
88     var payload = new Buffer(buffer, 'utf8'),
89         frame   = new Buffer(payload.length + 2);
90
91     frame[0] = 0x00;
92     frame[payload.length + 1] = 0xFF;
93     payload.copy(frame, 1);
94
95     this._write(frame);
96     return true;
97   },
98
99   _handshakeResponse: function() {
100     var start   = 'HTTP/1.1 101 Web Socket Protocol Handshake',
101         headers = [start, this._headers.toString(), ''];
102
103     return new Buffer(headers.join('\r\n'), 'utf8');
104   },
105
106   _parseLeadingByte: function(octet) {
107     if ((octet & 0x80) === 0x80) {
108       this._length = 0;
109       this._stage  = 1;
110     } else {
111       delete this._length;
112       delete this._skipped;
113       this._buffer = [];
114       this._stage  = 2;
115     }
116   }
117 };
118
119 for (var key in instance)
120   Draft75.prototype[key] = instance[key];
121
122 module.exports = Draft75;