From 5809642ae0f1b3199bb2920d4a5f118c8e5a6269 Mon Sep 17 00:00:00 2001 From: Jan Antala Date: Thu, 7 May 2015 21:52:31 +0200 Subject: [PATCH 1/8] ADD registration creation date --- lib/services/server/mongodbDeviceRegistry.js | 1 + lib/services/server/registration.js | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/services/server/mongodbDeviceRegistry.js b/lib/services/server/mongodbDeviceRegistry.js index 9f17dd7..fec3b53 100644 --- a/lib/services/server/mongodbDeviceRegistry.js +++ b/lib/services/server/mongodbDeviceRegistry.js @@ -129,6 +129,7 @@ function register(object, callback) { deviceObj.lifetime = object.lifetime; deviceObj.name = object.name; deviceObj.type = object.type; + deviceObj.creationDate = object.creationDate; deviceObj.save(innerCb); } diff --git a/lib/services/server/registration.js b/lib/services/server/registration.js index 450c995..8500b45 100644 --- a/lib/services/server/registration.js +++ b/lib/services/server/registration.js @@ -76,7 +76,8 @@ function storeDevice(queryParams, req, callback) { name: queryParams.ep, lifetime: queryParams.lt, address: req.rsinfo.address, - port: req.rsinfo.port + port: req.rsinfo.port, + creationDate: new Date() }; logger.debug(context, 'Storing the following device in the db:\n%s', JSON.stringify(device, null, 4)); From 21c2f6dff930aa7e686d79314550c5c1a1a1c071 Mon Sep 17 00:00:00 2001 From: Jan Antala Date: Thu, 7 May 2015 22:05:44 +0200 Subject: [PATCH 2/8] ADD update registration creation date --- lib/services/server/mongodbDeviceRegistry.js | 8 +++++++- lib/services/server/updateRegistration.js | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/services/server/mongodbDeviceRegistry.js b/lib/services/server/mongodbDeviceRegistry.js index fec3b53..9dec746 100644 --- a/lib/services/server/mongodbDeviceRegistry.js +++ b/lib/services/server/mongodbDeviceRegistry.js @@ -171,7 +171,13 @@ function update(id, obj, callback) { callback(error); } else { objDAO.id = obj.id; - objDAO.type = objDAO.type; + objDAO.address = obj.address; + objDAO.port = obj.port; + objDAO.path = obj.path; + objDAO.lifetime = obj.lifetime; + objDAO.name = obj.name; + objDAO.type = obj.type; + objDAO.creationDate = obj.creationDate; objDAO.save(toObject(callback)); } }); diff --git a/lib/services/server/updateRegistration.js b/lib/services/server/updateRegistration.js index 3ca76af..07d2969 100644 --- a/lib/services/server/updateRegistration.js +++ b/lib/services/server/updateRegistration.js @@ -61,9 +61,10 @@ function endUpdate(req, res) { function updateRegister(req, queryParams, obj, callback) { logger.debug(context, 'Updating device register with lifetime [%s] and address [%s].', queryParams.lt, req.rsinfo.address); - obj.lifetime = queryParams.lt; + obj.lifetime = queryParams.lt || obj.lifetime; obj.address = req.rsinfo.address; obj.port = req.rsinfo.port; + obj.creationDate = new Date(); callback(null, obj); } From af8a4c29a95474526329f93057d13b9ee9216df0 Mon Sep 17 00:00:00 2001 From: Jan Antala Date: Thu, 7 May 2015 22:42:45 +0200 Subject: [PATCH 3/8] ADD Unregister device when the lifetime is exceeded --- lib/lwm2m-server.js | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/lwm2m-server.js b/lib/lwm2m-server.js index 8f7a165..e619c6a 100644 --- a/lib/lwm2m-server.js +++ b/lib/lwm2m-server.js @@ -35,7 +35,8 @@ var coapRouter = require('./services/coapRouter'), op: 'LWM2MLib.Server' }, apply = async.apply, - status = 'STOPPED'; + status = 'STOPPED', + checkLifetimeInterval; /** * Load the internal handlers for each kind of operation. Each handler is implemented in a separated module. This @@ -103,6 +104,29 @@ function validateTypes(config, callback) { callback(error); } +/** + * If Lifetime Resource exists, then the registration SHOULD be removed by the Server if a new registration or update + * is not received within this lifetime. + */ +function checkLifetime() { + var CHECK_INTERVAL = 1000; + + return setInterval(function(){ + registry.list(function(error, deviceList){ + if (!error && deviceList) { + deviceList.forEach(function(device){ + if (device.lifetime && + new Date() - new Date(device.creationDate) > Number(device.lifetime) * 1000) { + registry.unregister(device.id, function(err, obj){ + + }); + } + }); + } + }); + }, CHECK_INTERVAL); +} + function start(config, startCallback) { function loadDefaults(serverInfo, callback) { loadRoutes(serverInfo); @@ -141,6 +165,7 @@ function start(config, startCallback) { status = 'ERROR'; } else { status = 'RUNNING'; + checkLifetimeInterval = checkLifetime(); } startCallback(error, results); @@ -149,6 +174,8 @@ function start(config, startCallback) { function stop(deviceInfo, callback) { status = 'STOPPED'; + clearInterval(checkLifetimeInterval); + checkLifetimeInterval = null; async.series([ informationReporting.clean, From 3e29f689ec5aa0a2e54420140c17019d7a2718f8 Mon Sep 17 00:00:00 2001 From: Jan Antala Date: Thu, 7 May 2015 22:49:56 +0200 Subject: [PATCH 4/8] ADD Changes to changelog --- CHANGES_NEXT_RELEASE | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index a2aa346..1dbb06e 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -5,3 +5,4 @@ - Fix command line break when executing command before starting the server (#47). - FIX Client handler after connection update (#51) - FIX Remove old device registration on the new registration (#52) +- Add Check lifetime and unregister devices (#56) From 5ff941f9e0a91822b3f26d343267f873d2af7c61 Mon Sep 17 00:00:00 2001 From: Jan Antala Date: Fri, 8 May 2015 16:26:13 +0200 Subject: [PATCH 5/8] ADD Lifetime unregistration debug logs --- lib/lwm2m-server.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/lwm2m-server.js b/lib/lwm2m-server.js index e619c6a..e1c8029 100644 --- a/lib/lwm2m-server.js +++ b/lib/lwm2m-server.js @@ -118,7 +118,16 @@ function checkLifetime() { if (device.lifetime && new Date() - new Date(device.creationDate) > Number(device.lifetime) * 1000) { registry.unregister(device.id, function(err, obj){ - + if (err) { + logger.debug(context, + 'Lifetime unregistration for device [%s] ended up in error [%s] with code [%s]', + obj.name, err.name, err.code); + } + else { + logger.debug(context, + 'Lifetime unregistration for device [%s] ended successfully', + obj.name); + } }); } }); From 8d3e310ad777d621cf3df8938e1b6ed6800d86da Mon Sep 17 00:00:00 2001 From: Jan Antala Date: Fri, 8 May 2015 17:25:02 +0200 Subject: [PATCH 6/8] ADD Lifetime unregistration into device registers --- config-mongo.js | 3 +- config.js | 3 + lib/lwm2m-server.js | 41 +------------- lib/services/server/inMemoryDeviceRegistry.js | 56 ++++++++++++++++++- lib/services/server/informationReporting.js | 5 ++ lib/services/server/mongodbDeviceRegistry.js | 56 +++++++++++++++++-- 6 files changed, 118 insertions(+), 46 deletions(-) diff --git a/config-mongo.js b/config-mongo.js index c27f52a..d0f6580 100644 --- a/config-mongo.js +++ b/config-mongo.js @@ -13,7 +13,8 @@ config.server = { type: 'mongodb', host: 'localhost', port: '27017', - db: 'lwtm2m' + db: 'lwtm2m', + lifetimeCheckInterval: 1000 // Minimum interval between lifetime checks in ms }, formats: [ { diff --git a/config.js b/config.js index fe988a2..90171d2 100644 --- a/config.js +++ b/config.js @@ -9,6 +9,9 @@ config.server = { logLevel: 'FATAL', ipProtocol: 'udp4', serverProtocol: 'udp4', + deviceRegistry: { + lifetimeCheckInterval: 1000 // Minimum interval between lifetime checks in ms + }, formats: [ { name: 'application-vnd-oma-lwm2m/text', diff --git a/lib/lwm2m-server.js b/lib/lwm2m-server.js index e1c8029..47989e7 100644 --- a/lib/lwm2m-server.js +++ b/lib/lwm2m-server.js @@ -35,8 +35,7 @@ var coapRouter = require('./services/coapRouter'), op: 'LWM2MLib.Server' }, apply = async.apply, - status = 'STOPPED', - checkLifetimeInterval; + status = 'STOPPED'; /** * Load the internal handlers for each kind of operation. Each handler is implemented in a separated module. This @@ -104,38 +103,6 @@ function validateTypes(config, callback) { callback(error); } -/** - * If Lifetime Resource exists, then the registration SHOULD be removed by the Server if a new registration or update - * is not received within this lifetime. - */ -function checkLifetime() { - var CHECK_INTERVAL = 1000; - - return setInterval(function(){ - registry.list(function(error, deviceList){ - if (!error && deviceList) { - deviceList.forEach(function(device){ - if (device.lifetime && - new Date() - new Date(device.creationDate) > Number(device.lifetime) * 1000) { - registry.unregister(device.id, function(err, obj){ - if (err) { - logger.debug(context, - 'Lifetime unregistration for device [%s] ended up in error [%s] with code [%s]', - obj.name, err.name, err.code); - } - else { - logger.debug(context, - 'Lifetime unregistration for device [%s] ended successfully', - obj.name); - } - }); - } - }); - } - }); - }, CHECK_INTERVAL); -} - function start(config, startCallback) { function loadDefaults(serverInfo, callback) { loadRoutes(serverInfo); @@ -166,7 +133,7 @@ function start(config, startCallback) { async.waterfall([ apply(validateTypes, config), - apply(registry.init, config), + apply(registry.init, config, context, logger), apply(coapRouter.start, config), loadDefaults ], function (error, results) { @@ -174,7 +141,7 @@ function start(config, startCallback) { status = 'ERROR'; } else { status = 'RUNNING'; - checkLifetimeInterval = checkLifetime(); + registry.checkLifetime(config.deviceRegistry.lifetimeCheckInterval); } startCallback(error, results); @@ -183,8 +150,6 @@ function start(config, startCallback) { function stop(deviceInfo, callback) { status = 'STOPPED'; - clearInterval(checkLifetimeInterval); - checkLifetimeInterval = null; async.series([ informationReporting.clean, diff --git a/lib/services/server/inMemoryDeviceRegistry.js b/lib/services/server/inMemoryDeviceRegistry.js index fd6e832..8ffe6f8 100644 --- a/lib/services/server/inMemoryDeviceRegistry.js +++ b/lib/services/server/inMemoryDeviceRegistry.js @@ -26,7 +26,10 @@ var registry = {}, idCounter = 1, errors = require('../../errors'), - _ = require('underscore'); + _ = require('underscore'), + context, + logger, + checkLifetimeInterval; /** * Gets the device that has the device name passed as a parameter (should be unique) or return a DeviceNotFound error @@ -147,13 +150,58 @@ function list(callback) { callback(null, result); } + +/** + * If Lifetime Resource exists, then the registration SHOULD be removed by the Server if a new registration or update + * is not received within this lifetime. + * + * @param {Object} lifetimeCheckInterval Minimum interval between lifetime checks in ms + */ +function checkLifetime(lifetimeCheckInterval) { + checkLifetimeInterval = setInterval(function(){ + list(function(error, deviceList){ + if (!error && deviceList) { + deviceList.forEach(function(device){ + if (device.lifetime && + new Date() - new Date(device.creationDate) > Number(device.lifetime) * 1000) { + unregister(device.id, function(err, obj){ + if (err) { + logger.debug(context, + 'Lifetime unregistration for device [%s] ended up in error [%s] with code [%s]', + obj.name, err.name, err.code); + } + else { + logger.debug(context, + 'Lifetime unregistration for device [%s] ended successfully', + obj.name); + } + }); + } + }); + } + }); + }, lifetimeCheckInterval); +} + +/** + * Stops checking for device lifetime. + */ +function stopLifetimeCheck() { + clearInterval(checkLifetimeInterval); + checkLifetimeInterval = null; +} + /** * Initializes the device registry based on the parameter found in the configuration. For this in memory registry this * function doesn't do anything. * - * @param {Object} config Configuration object. + * @param {Object} newConfig Configuration object. + * @param {Object} newContext Context object. + * @param {Object} newLogger Logger object. */ -function init(config, callback) { +function init(newConfig, newContext, newLogger, callback) { + context = newContext; + logger = newLogger; callback(null); } @@ -163,5 +211,7 @@ exports.get = getObject; exports.update = update; exports.clean = clean; exports.list = list; +exports.checkLifetime = checkLifetime; +exports.stopLifetimeCheck = stopLifetimeCheck; exports.getByName = getByName; exports.init = init; diff --git a/lib/services/server/informationReporting.js b/lib/services/server/informationReporting.js index 314768d..3665fa6 100644 --- a/lib/services/server/informationReporting.js +++ b/lib/services/server/informationReporting.js @@ -193,6 +193,11 @@ function clean(callback) { } subscriptions = {}; + + if (registry){ + registry.stopLifetimeCheck(); + } + callback(); } diff --git a/lib/services/server/mongodbDeviceRegistry.js b/lib/services/server/mongodbDeviceRegistry.js index 9dec746..24d84bd 100644 --- a/lib/services/server/mongodbDeviceRegistry.js +++ b/lib/services/server/mongodbDeviceRegistry.js @@ -25,7 +25,10 @@ var errors = require('../../errors'), dbService = require('../model/dbConn'), - Device = require('../model/Device'); + Device = require('../model/Device'), + context, + logger, + checkLifetimeInterval; /** * Generic function to retrieve a device based on a parameter value. This is an auxiliary function meant to abstract @@ -195,16 +198,59 @@ function list(callback) { query.exec(callback); } +/** + * If Lifetime Resource exists, then the registration SHOULD be removed by the Server if a new registration or update + * is not received within this lifetime. + * + * @param {Object} lifetimeCheckInterval Minimum interval between lifetime checks in ms + */ +function checkLifetime(lifetimeCheckInterval) { + checkLifetimeInterval = setInterval(function(){ + list(function(error, deviceList){ + if (!error && deviceList) { + deviceList.forEach(function(device){ + if (device.lifetime && + new Date() - new Date(device.creationDate) > Number(device.lifetime) * 1000) { + unregister(device.id, function(err, obj){ + if (err) { + logger.debug(context, + 'Lifetime unregistration for device [%s] ended up in error [%s] with code [%s]', + obj.name, err.name, err.code); + } + else { + logger.debug(context, + 'Lifetime unregistration for device [%s] ended successfully', + obj.name); + } + }); + } + }); + } + }); + }, lifetimeCheckInterval); +} + +/** + * Stops checking for device lifetime. + */ +function stopLifetimeCheck() { + clearInterval(checkLifetimeInterval); + checkLifetimeInterval = null; +} + /** * Initializes the device registry based on the parameter found in the configuration. The MongoDB config object should * contain at least the host string needed to connect to MongoDB and the database name where to store the device info. * The configuration object to use should be the one corresponding to the general server configuration, although all * the Mongo specific information should be stored under the 'deviceRegistry' section. * - * @param {Object} config Configuration object containing a deviceRegistry attribute with the info. + * @param {Object} newConfig Configuration object containing a deviceRegistry attribute with the info. + * @param {Object} newContext Context object. + * @param {Object} newLogger Logger object. */ - -function init(newConfig, callback) { +function init(newConfig, newContext, newLogger, callback) { + context = newContext; + logger = newLogger; dbService.init(newConfig.deviceRegistry.host, newConfig.deviceRegistry.db, callback); } @@ -214,5 +260,7 @@ exports.get = getObject; exports.update = update; exports.clean = clean; exports.list = list; +exports.checkLifetime = checkLifetime; +exports.stopLifetimeCheck = stopLifetimeCheck; exports.getByName = getByName; exports.init = init; From 10fd25e1aa45ebe7531678d81e22671f671431ba Mon Sep 17 00:00:00 2001 From: Jan Antala Date: Fri, 8 May 2015 22:04:18 +0200 Subject: [PATCH 7/8] ADD Lifetime check interval config --- config-mongo.js | 4 ++-- config.js | 4 +--- lib/lwm2m-server.js | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/config-mongo.js b/config-mongo.js index d0f6580..c4fd4d7 100644 --- a/config-mongo.js +++ b/config-mongo.js @@ -4,6 +4,7 @@ var config = {}; //-------------------------------------------------- config.server = { port: 5683, // Port where the server will be listening + lifetimeCheckInterval: 1000, // Minimum interval between lifetime checks in ms udpWindow: 100, defaultType: 'Device', logLevel: 'FATAL', @@ -13,8 +14,7 @@ config.server = { type: 'mongodb', host: 'localhost', port: '27017', - db: 'lwtm2m', - lifetimeCheckInterval: 1000 // Minimum interval between lifetime checks in ms + db: 'lwtm2m' }, formats: [ { diff --git a/config.js b/config.js index 90171d2..160d1f1 100644 --- a/config.js +++ b/config.js @@ -4,14 +4,12 @@ var config = {}; //-------------------------------------------------- config.server = { port: 5683, // Port where the server will be listening + lifetimeCheckInterval: 1000, // Minimum interval between lifetime checks in ms udpWindow: 100, defaultType: 'Device', logLevel: 'FATAL', ipProtocol: 'udp4', serverProtocol: 'udp4', - deviceRegistry: { - lifetimeCheckInterval: 1000 // Minimum interval between lifetime checks in ms - }, formats: [ { name: 'application-vnd-oma-lwm2m/text', diff --git a/lib/lwm2m-server.js b/lib/lwm2m-server.js index 47989e7..108e6cf 100644 --- a/lib/lwm2m-server.js +++ b/lib/lwm2m-server.js @@ -141,7 +141,7 @@ function start(config, startCallback) { status = 'ERROR'; } else { status = 'RUNNING'; - registry.checkLifetime(config.deviceRegistry.lifetimeCheckInterval); + registry.checkLifetime(config.lifetimeCheckInterval); } startCallback(error, results); From 1ed12ef84cc7f083a8b36a2a24fb52cfaa769fd8 Mon Sep 17 00:00:00 2001 From: Jan Antala Date: Mon, 11 May 2015 09:21:04 +0200 Subject: [PATCH 8/8] ADD Device registry context --- lib/lwm2m-server.js | 2 +- lib/services/server/inMemoryDeviceRegistry.js | 17 +++++++++-------- lib/services/server/mongodbDeviceRegistry.js | 19 ++++++++++--------- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/lib/lwm2m-server.js b/lib/lwm2m-server.js index 108e6cf..ff69265 100644 --- a/lib/lwm2m-server.js +++ b/lib/lwm2m-server.js @@ -133,7 +133,7 @@ function start(config, startCallback) { async.waterfall([ apply(validateTypes, config), - apply(registry.init, config, context, logger), + apply(registry.init, config), apply(coapRouter.start, config), loadDefaults ], function (error, results) { diff --git a/lib/services/server/inMemoryDeviceRegistry.js b/lib/services/server/inMemoryDeviceRegistry.js index 8ffe6f8..8a46980 100644 --- a/lib/services/server/inMemoryDeviceRegistry.js +++ b/lib/services/server/inMemoryDeviceRegistry.js @@ -27,8 +27,10 @@ var registry = {}, idCounter = 1, errors = require('../../errors'), _ = require('underscore'), - context, - logger, + logger = require('logops'), + context = { + op: 'LWM2MLib.MemoryDeviceRegistry' + }, checkLifetimeInterval; /** @@ -195,13 +197,12 @@ function stopLifetimeCheck() { * Initializes the device registry based on the parameter found in the configuration. For this in memory registry this * function doesn't do anything. * - * @param {Object} newConfig Configuration object. - * @param {Object} newContext Context object. - * @param {Object} newLogger Logger object. + * @param {Object} config Configuration object. */ -function init(newConfig, newContext, newLogger, callback) { - context = newContext; - logger = newLogger; +function init(config, callback) { + if (config.logLevel) { + logger.setLevel(config.logLevel); + } callback(null); } diff --git a/lib/services/server/mongodbDeviceRegistry.js b/lib/services/server/mongodbDeviceRegistry.js index 24d84bd..ae507f8 100644 --- a/lib/services/server/mongodbDeviceRegistry.js +++ b/lib/services/server/mongodbDeviceRegistry.js @@ -26,8 +26,10 @@ var errors = require('../../errors'), dbService = require('../model/dbConn'), Device = require('../model/Device'), - context, - logger, + logger = require('logops'), + context = { + op: 'LWM2MLib.MomgodbDeviceRegistry' + }, checkLifetimeInterval; /** @@ -244,14 +246,13 @@ function stopLifetimeCheck() { * The configuration object to use should be the one corresponding to the general server configuration, although all * the Mongo specific information should be stored under the 'deviceRegistry' section. * - * @param {Object} newConfig Configuration object containing a deviceRegistry attribute with the info. - * @param {Object} newContext Context object. - * @param {Object} newLogger Logger object. + * @param {Object} config Configuration object containing a deviceRegistry attribute with the info. */ -function init(newConfig, newContext, newLogger, callback) { - context = newContext; - logger = newLogger; - dbService.init(newConfig.deviceRegistry.host, newConfig.deviceRegistry.db, callback); +function init(config, callback) { + if (config.logLevel) { + logger.setLevel(config.logLevel); + } + dbService.init(config.deviceRegistry.host, config.deviceRegistry.db, callback); } exports.register = register;