diff --git a/lib/device-tracker.js b/lib/device-tracker.js index 7194cdf..f5ed895 100644 --- a/lib/device-tracker.js +++ b/lib/device-tracker.js @@ -2,9 +2,24 @@ var Devices = module.exports; Devices.add = function (store, servername, newDevice) { - var devices = store[servername] || []; + if (!store[servername]) { + store[servername] = []; + } + var devices = store[servername]; devices.push(newDevice); - store[servername] = devices; +}; +Devices.alias = function (store, servername, alias) { + if (!store[servername]) { + store[servername] = []; + } + if (!store[servername]._primary) { + store[servername]._primary = servername; + } + if (!store[servername].aliases) { + store[servername].aliases = {}; + } + store[alias] = store[servername]; + store[servername].aliases[alias] = true; }; Devices.remove = function (store, servername, device) { var devices = store[servername] || []; @@ -17,9 +32,11 @@ Devices.remove = function (store, servername, device) { return devices.splice(index, 1)[0]; }; Devices.list = function (store, servername) { + // efficient lookup first if (store[servername] && store[servername].length) { - return store[servername]; + return store[servername]._primary && store[store[servername]._primary] || store[servername]; } + // There wasn't an exact match so check any of the wildcard domains, sorted longest // first so the one with the biggest natural match with be found first. var deviceList = []; @@ -28,10 +45,19 @@ Devices.list = function (store, servername) { }).sort(function (a, b) { return b.length - a.length; }).some(function (pattern) { + // '.example.com' = '*.example.com'.split(1) var subPiece = pattern.slice(1); + // '.com' = 'sub.example.com'.slice(-4) + // '.example.com' = 'sub.example.com'.slice(-12) if (subPiece === servername.slice(-subPiece.length)) { - console.log('"'+servername+'" matches "'+pattern+'"'); + console.log('[Devices.list] "'+servername+'" matches "'+pattern+'"'); deviceList = store[pattern]; + + // Devices.alias(store, '*.example.com', 'sub.example.com' + // '*.example.com' retrieves a reference to 'example.com' + // and this reference then also referenced by 'sub.example.com' + // Hence this O(n) check is replaced with the O(1) check above + Devices.alias(store, pattern, servername); return true; } }); diff --git a/lib/relay.js b/lib/relay.js index 156b392..78c159b 100644 --- a/lib/relay.js +++ b/lib/relay.js @@ -307,6 +307,8 @@ var Server = { console.log('add', domainname, 'to device lists'); srv.domainsMap[domainname] = true; Devices.add(state.deviceLists, domainname, srv); + // TODO allow subs to go to individual devices + Devices.alias(state.deviceLists, domainname, '*.' + domainname); }); srv.domains = Object.keys(srv.domainsMap); srv.currentDesc = (grant.device && (grant.device.id || grant.device.hostname)) || srv.domains.join(',');