Initial commit
[yaffs-website] / node_modules / websocket-driver / lib / websocket / driver / proxy.js
1 'use strict';
2
3 var Stream     = require('stream').Stream,
4     url        = require('url'),
5     util       = require('util'),
6     Base       = require('./base'),
7     Headers    = require('./headers'),
8     HttpParser = require('../http_parser');
9
10 var PORTS = {'ws:': 80, 'wss:': 443};
11
12 var Proxy = function(client, origin, options) {
13   this._client  = client;
14   this._http    = new HttpParser('response');
15   this._origin  = (typeof client.url === 'object') ? client.url : url.parse(client.url);
16   this._url     = (typeof origin === 'object') ? origin : url.parse(origin);
17   this._options = options || {};
18   this._state   = 0;
19
20   this.readable = this.writable = true;
21   this._paused  = false;
22
23   this._headers = new Headers();
24   this._headers.set('Host', this._origin.host);
25   this._headers.set('Connection', 'keep-alive');
26   this._headers.set('Proxy-Connection', 'keep-alive');
27
28   var auth = this._url.auth && new Buffer(this._url.auth, 'utf8').toString('base64');
29   if (auth) this._headers.set('Proxy-Authorization', 'Basic ' + auth);
30 };
31 util.inherits(Proxy, Stream);
32
33 var instance = {
34   setHeader: function(name, value) {
35     if (this._state !== 0) return false;
36     this._headers.set(name, value);
37     return true;
38   },
39
40   start: function() {
41     if (this._state !== 0) return false;
42     this._state = 1;
43
44     var origin = this._origin,
45         port   = origin.port || PORTS[origin.protocol],
46         start  = 'CONNECT ' + origin.hostname + ':' + port + ' HTTP/1.1';
47
48     var headers = [start, this._headers.toString(), ''];
49
50     this.emit('data', new Buffer(headers.join('\r\n'), 'utf8'));
51     return true;
52   },
53
54   pause: function() {
55     this._paused = true;
56   },
57
58   resume: function() {
59     this._paused = false;
60     this.emit('drain');
61   },
62
63   write: function(chunk) {
64     if (!this.writable) return false;
65
66     this._http.parse(chunk);
67     if (!this._http.isComplete()) return !this._paused;
68
69     this.statusCode = this._http.statusCode;
70     this.headers    = this._http.headers;
71
72     if (this.statusCode === 200) {
73       this.emit('connect', new Base.ConnectEvent());
74     } else {
75       var message = "Can't establish a connection to the server at " + this._origin.href;
76       this.emit('error', new Error(message));
77     }
78     this.end();
79     return !this._paused;
80   },
81
82   end: function(chunk) {
83     if (!this.writable) return;
84     if (chunk !== undefined) this.write(chunk);
85     this.readable = this.writable = false;
86     this.emit('close');
87     this.emit('end');
88   },
89
90   destroy: function() {
91     this.end();
92   }
93 };
94
95 for (var key in instance)
96   Proxy.prototype[key] = instance[key];
97
98 module.exports = Proxy;