Commit | Line | Data |
---|---|---|
a8bf3ea4 JA |
1 | var ws = require('socket.io'), |
2 | events = require('events'), | |
3 | http = require('http'), | |
4 | https = require('https'), | |
5 | util = require('util'), | |
6 | fs = require('fs'), | |
7 | dns = require('dns'), | |
186531ed | 8 | url = require('url'), |
f9ff7686 | 9 | _ = require('lodash'), |
1286229a D |
10 | Client = require('./client.js').Client, |
11 | HttpHandler = require('./httphandler.js').HttpHandler, | |
f2fb32b7 D |
12 | rehash = require('./rehash.js'), |
13 | range_check = require('range_check'); | |
1286229a D |
14 | |
15 | ||
16 | ||
17 | rehash.on('rehashed', function (files) { | |
18 | Client = require('./client.js').Client; | |
2f1e8a71 | 19 | HttpHandler = require('./httphandler.js').HttpHandler; |
1286229a D |
20 | }); |
21 | ||
186531ed D |
22 | |
23 | // Instance of HttpHandler | |
24 | var http_handler; | |
25 | ||
a8bf3ea4 | 26 | |
8b0eb787 | 27 | var WebListener = function (web_config, transports) { |
71c81a3b | 28 | var hs, opts, ws_opts, |
a8bf3ea4 JA |
29 | that = this; |
30 | ||
71c81a3b | 31 | |
a8bf3ea4 JA |
32 | events.EventEmitter.call(this); |
33 | ||
8b0eb787 | 34 | http_handler = new HttpHandler(web_config); |
a8bf3ea4 | 35 | |
71c81a3b D |
36 | // Standard options for the socket.io connections |
37 | ws_opts = { | |
38 | 'log level': 0, | |
39 | 'log colors': 0 | |
40 | }; | |
41 | ||
42 | ||
8b0eb787 | 43 | if (web_config.ssl) { |
a8bf3ea4 | 44 | opts = { |
8b0eb787 D |
45 | key: fs.readFileSync(__dirname + '/' + web_config.ssl_key), |
46 | cert: fs.readFileSync(__dirname + '/' + web_config.ssl_cert) | |
a8bf3ea4 | 47 | }; |
186531ed | 48 | |
a8bf3ea4 | 49 | // Do we have an intermediate certificate? |
8b0eb787 D |
50 | if (typeof web_config.ssl_ca !== 'undefined') { |
51 | opts.ca = fs.readFileSync(__dirname + '/' + web_config.ssl_ca); | |
a8bf3ea4 | 52 | } |
186531ed D |
53 | |
54 | ||
55 | hs = https.createServer(opts, handleHttpRequest); | |
a8bf3ea4 | 56 | |
186531ed | 57 | // Start socket.io listening on this weblistener |
71c81a3b | 58 | this.ws = ws.listen(hs, _.extend({ssl: true}, ws_opts)); |
e380bc9e D |
59 | hs.listen(web_config.port, web_config.address, function () { |
60 | that.emit('listening'); | |
61 | }); | |
186531ed | 62 | |
8b0eb787 | 63 | console.log('Listening on ' + web_config.address + ':' + web_config.port.toString() + ' with SSL'); |
a8bf3ea4 | 64 | } else { |
186531ed | 65 | |
a8bf3ea4 | 66 | // Start some plain-text server up |
186531ed D |
67 | hs = http.createServer(handleHttpRequest); |
68 | ||
69 | // Start socket.io listening on this weblistener | |
71c81a3b | 70 | this.ws = ws.listen(hs, _.extend({ssl: false}, ws_opts)); |
e380bc9e D |
71 | hs.listen(web_config.port, web_config.address, function () { |
72 | that.emit('listening'); | |
73 | }); | |
186531ed | 74 | |
8b0eb787 | 75 | console.log('Listening on ' + web_config.address + ':' + web_config.port.toString() + ' without SSL'); |
a8bf3ea4 JA |
76 | } |
77 | ||
a8bf3ea4 JA |
78 | this.ws.enable('browser client minification'); |
79 | this.ws.enable('browser client etag'); | |
80 | this.ws.set('transports', transports); | |
b737610b | 81 | this.ws.set('resource', (global.config.http_base_path || '') + '/transport'); |
a8bf3ea4 | 82 | |
c6e3ed44 D |
83 | this.ws.of('/kiwi').authorization(authoriseConnection) |
84 | .on('connection', function () { | |
85 | newConnection.apply(that, arguments); | |
86 | } | |
87 | ); | |
a8bf3ea4 JA |
88 | this.ws.of('/kiwi').on('error', console.log); |
89 | }; | |
90 | util.inherits(WebListener, events.EventEmitter); | |
91 | ||
186531ed D |
92 | |
93 | ||
94 | function handleHttpRequest(request, response) { | |
95 | var uri = url.parse(request.url, true); | |
96 | ||
97 | // If this isn't a socket.io request, pass it onto the http handler | |
98 | if (uri.pathname.substr(0, 10) !== '/socket.io') { | |
99 | http_handler.serve(request, response); | |
100 | } | |
101 | } | |
102 | ||
a8bf3ea4 | 103 | |
15fefff7 D |
104 | /** |
105 | * Get the reverse DNS entry for this connection. | |
106 | * Used later on for webirc, etc functionality | |
107 | */ | |
772a4bb6 | 108 | function authoriseConnection(handshakeData, callback) { |
c6e3ed44 D |
109 | var address = handshakeData.address.address; |
110 | ||
111 | // If a forwarded-for header is found, switch the source address | |
f2fb32b7 | 112 | if (handshakeData.headers[global.config.http_proxy_ip_header || 'x-forwarded-for']) { |
c6e3ed44 | 113 | // Check we're connecting from a whitelisted proxy |
f2fb32b7 | 114 | if (!global.config.http_proxies || !range_check.in_range(address, global.config.http_proxies)) { |
c6e3ed44 D |
115 | console.log('Unlisted proxy:', address); |
116 | callback(null, false); | |
117 | return; | |
118 | } | |
119 | ||
120 | // We're sent from a whitelisted proxy, replace the hosts | |
121 | address = handshakeData.headers['x-forwarded-for']; | |
122 | } | |
123 | ||
c36ed4eb JA |
124 | handshakeData.real_address = address; |
125 | ||
13d7faa3 | 126 | // If enabled, don't go over the connection limit |
b737610b JA |
127 | if (global.config.max_client_conns && global.config.max_client_conns > 0) { |
128 | if (global.clients.numOnAddress(address) + 1 > global.config.max_client_conns) { | |
13d7faa3 D |
129 | return callback(null, false); |
130 | } | |
c36ed4eb | 131 | } |
13d7faa3 | 132 | |
c6e3ed44 | 133 | dns.reverse(address, function (err, domains) { |
15fefff7 | 134 | if (err || domains.length === 0) { |
c6e3ed44 | 135 | handshakeData.revdns = address; |
15fefff7 | 136 | } else { |
c6e3ed44 | 137 | handshakeData.revdns = _.first(domains) || address; |
15fefff7 D |
138 | } |
139 | ||
c6e3ed44 | 140 | // All is well, authorise the connection |
a8bf3ea4 JA |
141 | callback(null, true); |
142 | }); | |
15fefff7 | 143 | } |
a8bf3ea4 | 144 | |
772a4bb6 | 145 | function newConnection(websocket) { |
c36ed4eb JA |
146 | var client, that = this; |
147 | client = new Client(websocket); | |
148 | client.on('destroy', function () { | |
149 | that.emit('destroy', this); | |
150 | }); | |
151 | this.emit('connection', client); | |
15fefff7 | 152 | } |
186531ed D |
153 | |
154 | ||
155 | ||
156 | ||
157 | ||
158 | module.exports = WebListener; |