diff --git a/lib/ago-test.js b/lib/ago-test.js new file mode 100644 index 0000000..8f67199 --- /dev/null +++ b/lib/ago-test.js @@ -0,0 +1,35 @@ +'use strict'; + +var timeago = require('./ago.js').AGO; + +function test() { + [ 1.5 * 1000 // a moment ago + , 4.5 * 1000 // moments ago + , 10 * 1000 // 10 seconds ago + , 59 * 1000 // a minute ago + , 60 * 1000 // a minute ago + , 61 * 1000 // a minute ago + , 119 * 1000 // a minute ago + , 120 * 1000 // 2 minutes ago + , 121 * 1000 // 2 minutes ago + , (60 * 60 * 1000) - 1000 // 59 minutes ago + , 1 * 60 * 60 * 1000 // an hour ago + , 1.5 * 60 * 60 * 1000 // an hour ago + , 2.5 * 60 * 60 * 1000 // 2 hours ago + , 1.5 * 24 * 60 * 60 * 1000 // a day ago + , 2.5 * 24 * 60 * 60 * 1000 // 2 days ago + , 7 * 24 * 60 * 60 * 1000 // a week ago + , 14 * 24 * 60 * 60 * 1000 // 2 weeks ago + , 27 * 24 * 60 * 60 * 1000 // 3 weeks ago + , 28 * 24 * 60 * 60 * 1000 // 4 weeks ago + , 29 * 24 * 60 * 60 * 1000 // 4 weeks ago + , 1.5 * 30 * 24 * 60 * 60 * 1000 // a month ago + , 2.5 * 30 * 24 * 60 * 60 * 1000 // 2 months ago + , (12 * 30 * 24 * 60 * 60 * 1000) + 1000 // 12 months ago + , 13 * 30 * 24 * 60 * 60 * 1000 // over a year ago + ].forEach(function (d) { + console.log(d, '=', timeago(d)); + }); +} + +test(); diff --git a/lib/ago.js b/lib/ago.js new file mode 100644 index 0000000..2728988 --- /dev/null +++ b/lib/ago.js @@ -0,0 +1,50 @@ +;(function (exports) { +'use strict'; + +exports.AGO = function timeago(ms) { + var ago = Math.floor(ms / 1000); + var part = 0; + + if (ago < 2) { return "a moment ago"; } + if (ago < 5) { return "moments ago"; } + if (ago < 60) { return ago + " seconds ago"; } + + if (ago < 120) { return "a minute ago"; } + if (ago < 3600) { + while (ago >= 60) { ago -= 60; part += 1; } + return part + " minutes ago"; + } + + if (ago < 7200) { return "an hour ago"; } + if (ago < 86400) { + while (ago >= 3600) { ago -= 3600; part += 1; } + return part + " hours ago"; + } + + if (ago < 172800) { return "a day ago"; } + if (ago < 604800) { + while (ago >= 172800) { ago -= 172800; part += 1; } + return part + " days ago"; + } + + if (ago < 1209600) { return "a week ago"; } + if (ago < 2592000) { + while (ago >= 604800) { ago -= 604800; part += 1; } + return part + " weeks ago"; + } + + if (ago < 5184000) { return "a month ago"; } + if (ago < 31536001) { + while (ago >= 2592000) { ago -= 2592000; part += 1; } + return part + " months ago"; + } + + if (ago < 315360000) { + return "more than year ago"; + } + + // TODO never + return ""; +}; + +}('undefined' !== typeof module ? module.exports : window)); diff --git a/lib/handlers.js b/lib/handlers.js index 4a94bc6..9250a34 100644 --- a/lib/handlers.js +++ b/lib/handlers.js @@ -72,9 +72,9 @@ module.exports.create = function (state) { state.tlsInvalidSniServer.on('tlsClientError', function () { console.error('tlsClientError InvalidSniServer'); }); - state.createHttpInvalid = function (servername) { + state.createHttpInvalid = function (opts) { return http.createServer(function (req, res) { - if (!servername) { + if (!opts.servername) { res.statusCode = 422; res.end( "3. An inexplicable temporal shift of the quantum realm... that makes me feel uncomfortable.\n\n" @@ -89,24 +89,25 @@ module.exports.create = function (state) { res.statusCode = 502; res.end( "
It looks like '" + encodeURIComponent(servername) + "' isn't connected right now.
" - + "Error: 502 Bad Gateway" + + "It looks like '" + encodeURIComponent(opts.servername) + "' isn't connected right now.
" + + "Last seen: " + opts.ago + "
" + + "Error: 502 Bad Gateway
" ); }); }; - state.httpsInvalid = function (servername, socket) { + state.httpsInvalid = function (opts, socket) { // none of these methods work: // httpsServer.emit('connection', socket); // this didn't work // tlsServer.emit('connection', socket); // this didn't work either //console.log('chunkLen', firstChunk.byteLength); - console.log('[httpsInvalid] servername', servername); + console.log('[httpsInvalid] servername', opts.servername); //state.tlsInvalidSniServer.emit('connection', wrapSocket(socket)); var tlsInvalidSniServer = tls.createServer(state.tlsOptions, function (tlsSocket) { console.log('[tlsInvalid] tls connection'); // We create an entire http server object because it's difficult to figure out // how to access the original tlsSocket to get the servername - state.createHttpInvalid(servername).emit('connection', tlsSocket); + state.createHttpInvalid(opts).emit('connection', tlsSocket); }); tlsInvalidSniServer.on('tlsClientError', function () { console.error('tlsClientError InvalidSniServer httpsInvalid'); diff --git a/lib/unwrap-tls.js b/lib/unwrap-tls.js index 46694fc..b6b2048 100644 --- a/lib/unwrap-tls.js +++ b/lib/unwrap-tls.js @@ -2,6 +2,16 @@ var sni = require('sni'); var pipeWs = require('./pipe-ws.js'); +var ago = require('./ago.js').AGO; +var up = Date.now(); + +function fromUptime(ms) { + if (ms) { + return ago(Date.now() - ms); + } else { + return "Not seen since relay restarted, " + ago(Date.now() - up); + } +} module.exports.createTcpConnectionHandler = function (state) { var Devices = state.Devices; @@ -48,7 +58,12 @@ module.exports.createTcpConnectionHandler = function (state) { // defer after return (instead of being in many places) function deferData(fn) { - if (fn) { + if ('httpsInvalid' === fn) { + state[fn]({ + servername: servername + , ago: fromUptime(Devices.lastSeen(state.deviceLists, servername)) + }, conn); + } else if (fn) { state[fn](servername, conn); } else { console.error("[SANITY ERROR] '" + fn + "' doesn't have a state handler"); @@ -96,7 +111,10 @@ module.exports.createTcpConnectionHandler = function (state) { // than creating a whole server object, but this is a "rare" // case and I'm feeling lazy right now. console.log("[debug] [http] no device connected"); - state.createHttpInvalid(servername).emit('connection', conn); + state.createHttpInvalid({ + servername: servername + , ago: fromUptime(Devices.lastSeen(state.deviceLists, servername)) + }).emit('connection', conn); return; }