Reverse HTTP proxies enabled on sicket.io connections
[KiwiIRC.git] / server / weblistener.js
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'),
8 url = require('url'),
9 _ = require('underscore'),
10 config = require('./configuration.js'),
11 Client = require('./client.js').Client,
12 HttpHandler = require('./httphandler.js').HttpHandler,
13 rehash = require('./rehash.js');
14
15
16
17 rehash.on('rehashed', function (files) {
18 Client = require('./client.js').Client;
19 HttpHandler = require('./httphandler.js').HttpHandler;
20 });
21
22
23 // Instance of HttpHandler
24 var http_handler;
25
26
27 var WebListener = function (web_config, transports) {
28 var hs,
29 opts,
30 that = this;
31
32 events.EventEmitter.call(this);
33
34 http_handler = new HttpHandler(web_config);
35
36 if (web_config.ssl) {
37 opts = {
38 key: fs.readFileSync(__dirname + '/' + web_config.ssl_key),
39 cert: fs.readFileSync(__dirname + '/' + web_config.ssl_cert)
40 };
41
42 // Do we have an intermediate certificate?
43 if (typeof web_config.ssl_ca !== 'undefined') {
44 opts.ca = fs.readFileSync(__dirname + '/' + web_config.ssl_ca);
45 }
46
47
48 hs = https.createServer(opts, handleHttpRequest);
49
50 // Start socket.io listening on this weblistener
51 this.ws = ws.listen(hs, {ssl: true});
52 hs.listen(web_config.port, web_config.address);
53
54 console.log('Listening on ' + web_config.address + ':' + web_config.port.toString() + ' with SSL');
55 } else {
56
57 // Start some plain-text server up
58 hs = http.createServer(handleHttpRequest);
59
60 // Start socket.io listening on this weblistener
61 this.ws = ws.listen(hs, {ssl: false});
62 hs.listen(web_config.port, web_config.address);
63
64 console.log('Listening on ' + web_config.address + ':' + web_config.port.toString() + ' without SSL');
65 }
66
67 this.ws.set('log level', 1);
68 this.ws.enable('browser client minification');
69 this.ws.enable('browser client etag');
70 this.ws.set('transports', transports);
71 this.ws.set('resource', (config.get().http_base_path || '') + '/transport');
72
73 this.ws.of('/kiwi').authorization(authoriseConnection)
74 .on('connection', function () {
75 newConnection.apply(that, arguments);
76 }
77 );
78 this.ws.of('/kiwi').on('error', console.log);
79 };
80 util.inherits(WebListener, events.EventEmitter);
81
82
83
84 function handleHttpRequest(request, response) {
85 var uri = url.parse(request.url, true);
86
87 // If this isn't a socket.io request, pass it onto the http handler
88 if (uri.pathname.substr(0, 10) !== '/socket.io') {
89 http_handler.serve(request, response);
90 }
91 }
92
93
94 /**
95 * Get the reverse DNS entry for this connection.
96 * Used later on for webirc, etc functionality
97 */
98 function authoriseConnection(handshakeData, callback) {
99 var address = handshakeData.address.address;
100
101 // If a forwarded-for header is found, switch the source address
102 if (handshakeData.headers['x-forwarded-for']) {
103 // Check we're connecting from a whitelisted proxy
104 if (!config.get().http_proxies || config.get().http_proxies.indexOf(address) < 0) {
105 console.log('Unlisted proxy:', address);
106 callback(null, false);
107 return;
108 }
109
110 // We're sent from a whitelisted proxy, replace the hosts
111 address = handshakeData.headers['x-forwarded-for'];
112 }
113
114 dns.reverse(address, function (err, domains) {
115 if (err || domains.length === 0) {
116 handshakeData.revdns = address;
117 } else {
118 handshakeData.revdns = _.first(domains) || address;
119 }
120
121 // All is well, authorise the connection
122 callback(null, true);
123 });
124 }
125
126 function newConnection(websocket) {
127 //console.log(websocket);
128 this.emit('connection', new Client(websocket));
129 }
130
131
132
133
134
135 module.exports = WebListener;