39c8b14f |
1 | #!/usr/bin/env node |
2 | |
3 | //growl('5 new emails', { title: 'Email Client' }); |
4 | //process.exit(0); |
5 | var argv = require('optimist').argv, bindhost="127.0.0.1", bindport="10080"; |
6 | if(argv.h || argv.help){ |
7 | console.log('usage: '+argv.$0+' [options] [bind-host]'); |
8 | console.log(''); |
9 | console.log('Options:'); |
10 | console.log('-q be quiet'); |
11 | console.log('-v verbose logging'); |
12 | process.exit(0); |
13 | } |
14 | if(argv._[0]){ |
15 | if(argv._[0].match(/^\d+\.\d+\.\d+\.\d+\:[0-9]{1,5}$/)){ |
16 | bindhost=argv._[0].split(":")[0]; |
17 | bindport=argv._[0].split(":")[1]; |
18 | } else { |
19 | console.error('Error: bind-host must be in the format [IP]:[PORT]'); |
20 | process.exit(0); |
21 | } |
22 | } |
23 | |
24 | require('./lib/IRC.js'); |
25 | global.argv=argv; |
26 | global.irc.loadScripts(); |
27 | global.settings = ''; |
28 | global.resume = ''; |
29 | |
30 | var http = require('http'), |
31 | WebSocketRequest = require('websocket').request, |
32 | ws = require('websocket-server'), |
33 | url = require('url'), |
34 | fs = require('fs'), |
35 | static = require('node-static'), |
36 | file = new(static.Server)('./public', { cache: 7200, headers: {'X-Hello':'World!'} }), |
37 | httpServer = http.createServer(function(request, response) { |
38 | var queryData = ""; |
39 | request.on('data', function(data) { |
40 | var path = url.parse(request.url).pathname; |
41 | if(path=="/resume"){ |
42 | queryData += data; |
43 | if(queryData.length > 1e6) { |
44 | queryData = ""; |
45 | response.writeHead(413, {'Content-Type': 'text/plain'}); |
46 | request.connection.destroy(); |
47 | } |
48 | } else if(path=="/settings"){ |
49 | queryData += data; |
50 | if(queryData.length > 1e6) { |
51 | queryData = ""; |
52 | response.writeHead(413, {'Content-Type': 'text/plain'}); |
53 | request.connection.destroy(); |
54 | } |
55 | } |
56 | }); |
57 | |
58 | request.addListener('end', function () { |
59 | var path = url.parse(request.url).pathname; |
60 | if(path=="/emoticons"){ |
61 | var emoticons = fs.readFileSync( |
62 | __dirname + '/public/images/emoticons/Emoticons.plist', 'utf8' |
63 | ); |
64 | response.writeHead(200, {"Content-Type": "application/xml"}); |
65 | response.end(emoticons); |
66 | } else if(path=="/resume"){ |
67 | response.writeHead(200, {"Content-Type": "application/json"}); |
68 | response.end(JSON.stringify(global.resume)); |
69 | if(queryData) { |
70 | global.resume=JSON.parse(queryData); |
71 | } |
72 | } else if(path=="/settings"){ |
73 | response.writeHead(200, {"Content-Type": "application/json"}); |
74 | response.end(JSON.stringify(global.settings)); |
75 | if(queryData) { |
76 | global.settings=JSON.parse(queryData); |
77 | } |
78 | } else{ |
79 | file.serve(request, response, function (err, res) { |
80 | if (err) { |
81 | console.error((new Date()) + " > Error serving " + request.url + " - " + err.message); |
82 | response.writeHead(err.status, err.headers); |
83 | response.end(); |
84 | } else { |
85 | if(argv.v) console.log((new Date()) + " > " + request.url + " - " + res.message); |
86 | } |
87 | }); |
88 | } |
89 | }); |
90 | }); |
91 | httpServer.listen(bindport, bindhost, function() { |
92 | if(!argv.q) console.log((new Date()) + " Server is listening on " + bindhost + ":" + bindport); |
93 | }); |
94 | |
95 | // node-websocket-server |
96 | var miksagoConnection = require('./node_modules/websocket-server/lib/ws/connection'); |
97 | var miksagoServer = ws.createServer(); |
98 | miksagoServer.server = httpServer; |
99 | miksagoServer.addListener('connection', function(connection) { |
100 | connection.remoteAddress = connection._socket.remoteAddress; |
101 | connection.sendUTF = connection.send; |
102 | handleConnection(connection); |
103 | }); |
104 | |
105 | |
106 | // WebSocket-Node config |
107 | |
108 | var wsServerConfig = { |
109 | // All options *except* 'httpServer' are required when bypassing |
110 | // WebSocketServer. |
111 | maxReceivedFrameSize: 0x10000, |
112 | maxReceivedMessageSize: 0x100000, |
113 | fragmentOutgoingMessages: true, |
114 | fragmentationThreshold: 0x4000, |
115 | keepalive: true, |
116 | keepaliveInterval: 20000, |
117 | assembleFragments: true, |
118 | // autoAcceptConnections is not applicable when bypassing WebSocketServer |
119 | // autoAcceptConnections: false, |
120 | disableNagleAlgorithm: true, |
121 | closeTimeout: 5000 |
122 | }; |
123 | |
124 | httpServer.on('upgrade', function(req, socket, head) { |
125 | if (typeof req.headers['sec-websocket-version'] !== 'undefined') { |
126 | // WebSocket hybi-08/-09/-10 connection (WebSocket-Node) |
127 | var wsRequest = new WebSocketRequest(socket, req, wsServerConfig); |
128 | try { |
129 | wsRequest.readHandshake(); |
130 | var wsConnection = wsRequest.accept(wsRequest.requestedProtocols[0], wsRequest.origin); |
131 | handleConnection(wsConnection); |
132 | } |
133 | catch(e) { |
134 | console.log("WebSocket Request unsupported by WebSocket-Node: " + e.toString()); |
135 | return; |
136 | } |
137 | } else { |
138 | // WebSocket hixie-75/-76/hybi-00 connection (node-websocket-server) |
139 | if (req.method === 'GET' && |
140 | (req.headers.upgrade && req.headers.connection) && |
141 | req.headers.upgrade.toLowerCase() === 'websocket' && |
142 | req.headers.connection.toLowerCase() === 'upgrade') { |
143 | new miksagoConnection(miksagoServer.manager, miksagoServer.options, req, socket, head); |
144 | } |
145 | } |
146 | }); |
147 | |
148 | function handleConnection(connection) { |
149 | if(!argv.q) console.log((new Date()) + " Connection accepted."); |
150 | global.websocket = connection; |
151 | connection.addListener('message', function(wsMessage) { |
152 | var message = wsMessage; |
153 | // WebSocket-Node adds a "type", node-websocket-server does not |
154 | if (typeof wsMessage.type !== 'undefined') { |
155 | if (wsMessage.type !== 'utf8') { |
156 | return; |
157 | } |
158 | message = wsMessage.utf8Data; |
159 | } |
160 | // console.log("Received Message: " + message); |
161 | if (message.match(/^CONNECT (.*)$/i)) { |
162 | var arrCmd = message.split(" "); |
163 | global.irc.connect(arrCmd[1], arrCmd[2], arrCmd[3], arrCmd[4], arrCmd[5], arrCmd[6]); |
164 | } else{ |
165 | global.irc.send(message); |
166 | } |
167 | }); |
168 | |
169 | connection.addListener('close', function() { |
170 | if(!argv.q) console.log((new Date()) + " Peer " + connection.remoteAddress + " disconnected."); |
171 | if(!global.resume || global.settings.hold != "on") { |
172 | global.irc.quit('BYE BYE'); |
173 | if(!argv.q) console.log((new Date()) + " Disconnected from IRC"); |
174 | } |
175 | }); |
176 | |
177 | } |
178 | if(!argv.n) require("openurl").open("http://" + bindhost + ":" + bindport); |