Compare commits

..
9 Commits
7 changed files with 109 additions and 40 deletions

No files matched your search

+8 -4
View File
@@ -130,15 +130,19 @@ connectionRequest = (deviceId, callback) ->
watchTask = (taskId, timeout, callback) -> watchTask = (taskId, timeout, callback) ->
setTimeout( () -> setTimeout( () ->
db.tasksCollection.findOne({_id : taskId}, {'_id' : 1}, (err, task) -> db.tasksCollection.findOne({_id : taskId}, {'_id' : 1, 'fault' : 1}, (err, task) ->
return callback(err) if err
if task if task
timeout -= 500 timeout -= 500
if timeout < 0 if task.fault?
callback('timeout') callback(null, 'fault')
else if timeout <= 0
callback(null, 'timeout')
else else
watchTask(taskId, timeout, callback) watchTask(taskId, timeout, callback)
else else
callback(err) callback(null, 'completed')
) )
, 500) , 500)
+6 -4
View File
@@ -173,7 +173,7 @@ inform = (currentRequest, cwmpRequest) ->
for k of reference for k of reference
continue if k[0] == '_' continue if k[0] == '_'
if not actual[k]?._timestamp? or actual[k]._timestamp < lastBootstrap if not actual[k]?._timestamp? or actual[k]._timestamp < lastBootstrap
_tasks.push({device: currentRequest.session.deviceId, name : 'refreshObject', objectName : reference[k]._path}) _tasks.push({device: currentRequest.session.deviceId, name : 'refreshObject', objectName : reference[k]._path, timestamp : now})
else else
traverse(reference[k], actual[k]) traverse(reference[k], actual[k])
@@ -186,7 +186,8 @@ inform = (currentRequest, cwmpRequest) ->
for cmd in customCommands.getDeviceCustomCommandNames(currentRequest.session.deviceId) for cmd in customCommands.getDeviceCustomCommandNames(currentRequest.session.deviceId)
if not (deviceCustomCommands[cmd]?._timestamp < lastBootstrap) if not (deviceCustomCommands[cmd]?._timestamp < lastBootstrap)
_tasks.push({device: currentRequest.session.deviceId, name: 'customCommand', command: "#{cmd} init"}) # Increment timestamp by one millisecond to ensure it runs after any refresh task
_tasks.push({device: currentRequest.session.deviceId, name: 'customCommand', command: "#{cmd} init", timestamp: new Date(now.getTime() + 1)})
delete deviceCustomCommands[cmd] delete deviceCustomCommands[cmd]
for cmd of deviceCustomCommands for cmd of deviceCustomCommands
@@ -210,10 +211,11 @@ inform = (currentRequest, cwmpRequest) ->
db.devicesCollection.insert({_id : currentRequest.session.deviceId, _registered : now, _deviceId : deviceIdDetails}, (err) -> db.devicesCollection.insert({_id : currentRequest.session.deviceId, _registered : now, _deviceId : deviceIdDetails}, (err) ->
throw err if err throw err if err
util.log("#{currentRequest.session.deviceId}: New device registered") util.log("#{currentRequest.session.deviceId}: New device registered")
_tasks.push({device: currentRequest.session.deviceId, name : 'refreshObject', objectName : ''}) _tasks.push({device: currentRequest.session.deviceId, name : 'refreshObject', objectName : '', timestamp : now})
for cmd in customCommands.getDeviceCustomCommandNames(currentRequest.session.deviceId) for cmd in customCommands.getDeviceCustomCommandNames(currentRequest.session.deviceId)
_tasks.push({device: currentRequest.session.deviceId, name: 'customCommand', command: "#{cmd} init"}) # Increment timestamp by one millisecond to ensure it runs after any refresh task
_tasks.push({device: currentRequest.session.deviceId, name: 'customCommand', command: "#{cmd} init", timestamp: new Date(now.getTime() + 1)})
apiFunctions.insertTasks(_tasks, {}, () -> apiFunctions.insertTasks(_tasks, {}, () ->
updateAndRespond() updateAndRespond()
+77 -22
View File
@@ -61,6 +61,10 @@ DEVICE_PRESET_REGEX = /^\/devices\/([a-zA-Z0-9\-\_\%]+)\/preset\/?$/
DELETE_DEVICE_REGEX = /^\/devices\/([a-zA-Z0-9\-\_\%]+)\/?$/ DELETE_DEVICE_REGEX = /^\/devices\/([a-zA-Z0-9\-\_\%]+)\/?$/
errorToString = (err) ->
"#{err.name}: #{err.message}"
listener = (request, response) -> listener = (request, response) ->
chunks = [] chunks = []
bytes = 0 bytes = 0
@@ -94,7 +98,7 @@ listener = (request, response) ->
) )
if err if err
response.writeHead(500) response.writeHead(500)
response.end(err) response.end(errorToString(err))
return return
response.writeHead(200) response.writeHead(200)
response.end() response.end()
@@ -106,8 +110,14 @@ listener = (request, response) ->
) )
if err if err
response.writeHead(500) response.writeHead(500)
response.end(err) response.end(errorToString(err))
return return
if removedCount == 0
response.writeHead(404)
response.end()
return
response.writeHead(200) response.writeHead(200)
response.end() response.end()
) )
@@ -126,7 +136,7 @@ listener = (request, response) ->
) )
if err if err
response.writeHead(500) response.writeHead(500)
response.end(err) response.end(errorToString(err))
return return
response.writeHead(200) response.writeHead(200)
response.end() response.end()
@@ -138,8 +148,14 @@ listener = (request, response) ->
) )
if err if err
response.writeHead(500) response.writeHead(500)
response.end(err) response.end(errorToString(err))
return return
if removedCount == 0
response.writeHead(404)
response.end()
return
response.writeHead(200) response.writeHead(200)
response.end() response.end()
) )
@@ -151,26 +167,38 @@ listener = (request, response) ->
deviceId = querystring.unescape(r[1]) deviceId = querystring.unescape(r[1])
tag = querystring.unescape(r[2]) tag = querystring.unescape(r[2])
if request.method == 'POST' if request.method == 'POST'
db.devicesCollection.update({'_id' : deviceId}, {'$addToSet' : {'_tags' : tag}}, {safe: true}, (err) -> db.devicesCollection.update({'_id' : deviceId}, {'$addToSet' : {'_tags' : tag}}, {safe: true}, (err, updatedCount) ->
db.redisClient.del("#{deviceId}_presets_hash", (err) -> db.redisClient.del("#{deviceId}_presets_hash", (err) ->
throw err if err throw err if err
) )
if err if err
response.writeHead(500) response.writeHead(500)
response.end(err) response.end(errorToString(err))
return return
if updatedCount == 0
response.writeHead(404)
response.end()
return
response.writeHead(200) response.writeHead(200)
response.end() response.end()
) )
else if request.method == 'DELETE' else if request.method == 'DELETE'
db.devicesCollection.update({'_id' : deviceId}, {'$pull' : {'_tags' : tag}}, {safe: true}, (err) -> db.devicesCollection.update({'_id' : deviceId}, {'$pull' : {'_tags' : tag}}, {safe: true}, (err, updatedCount) ->
db.redisClient.del("#{deviceId}_presets_hash", (err) -> db.redisClient.del("#{deviceId}_presets_hash", (err) ->
throw err if err throw err if err
) )
if err if err
response.writeHead(500) response.writeHead(500)
response.end(err) response.end(errorToString(err))
return return
if updatedCount == 0
response.writeHead(404)
response.end()
return
response.writeHead(200) response.writeHead(200)
response.end() response.end()
) )
@@ -190,22 +218,37 @@ listener = (request, response) ->
) )
if err if err
response.writeHead(500) response.writeHead(500)
response.end(err) response.end(errorToString(err))
return return
if urlParts.query.connection_request? if urlParts.query.connection_request?
apiFunctions.connectionRequest(deviceId, (err) -> apiFunctions.connectionRequest(deviceId, (err) ->
if err if err
response.writeHead(202, {'Content-Type' : 'application/json'}) response.writeHead(202, err.message, {'Content-Type' : 'application/json'})
response.end(JSON.stringify(task)) response.end(JSON.stringify(task))
else else
apiFunctions.watchTask(task._id, config.get('DEVICE_ONLINE_THRESHOLD', deviceId), (err) -> apiFunctions.watchTask(task._id, config.get('DEVICE_ONLINE_THRESHOLD', deviceId), (err, status) ->
if err if err
response.writeHead(202, {'Content-Type' : 'application/json'}) response.writeHead(500)
response.end(JSON.stringify(task)) response.end(errorToString(err))
return return
response.writeHead(200, {'Content-Type' : 'application/json'})
response.end(JSON.stringify(task)) if status is 'timeout'
response.writeHead(202, 'Task queued but not processed', {'Content-Type' : 'application/json'})
response.end(JSON.stringify(task))
else if status is 'fault'
db.tasksCollection.findOne({_id : task._id}, (err, task) ->
if err
response.writeHead(500)
response.end(errorToString(err))
return
response.writeHead(202, 'Task faulted', {'Content-Type' : 'application/json'})
response.end(JSON.stringify(task))
)
else
response.writeHead(200, {'Content-Type' : 'application/json'})
response.end(JSON.stringify(task))
) )
) )
else else
@@ -218,7 +261,7 @@ listener = (request, response) ->
apiFunctions.connectionRequest(deviceId, (err) -> apiFunctions.connectionRequest(deviceId, (err) ->
if err if err
response.writeHead 504 response.writeHead 504
response.end() response.end(errorToString(err))
return return
response.writeHead 200 response.writeHead 200
response.end() response.end()
@@ -250,8 +293,14 @@ listener = (request, response) ->
db.tasksCollection.remove({'_id' : taskId}, (err, removedCount) -> db.tasksCollection.remove({'_id' : taskId}, (err, removedCount) ->
if err if err
response.writeHead(500) response.writeHead(500)
response.end(err) response.end(errorToString(err))
return return
if removedCount == 0
response.writeHead(404)
response.end()
return
response.writeHead(200) response.writeHead(200)
response.end() response.end()
) )
@@ -260,8 +309,14 @@ listener = (request, response) ->
response.end('405 Method Not Allowed') response.end('405 Method Not Allowed')
else if action is '/retry' else if action is '/retry'
if request.method == 'POST' if request.method == 'POST'
db.tasksCollection.update({_id : taskId}, {$unset : {fault : 1}, $set : {timestamp : new Date()}}, (err, count) -> db.tasksCollection.update({_id : taskId}, {$unset : {fault : 1}, $set : {timestamp : new Date()}}, (err, updatedCount) ->
# TODO need to invalidate presets hash for the device # TODO need to invalidate presets hash for the device
throw err if err
if updatedCount == 0
response.writeHead(404)
response.end()
return
response.writeHead(200) response.writeHead(200)
response.end() response.end()
) )
@@ -303,9 +358,9 @@ listener = (request, response) ->
else if PING_REGEX.test(urlParts.pathname) else if PING_REGEX.test(urlParts.pathname)
host = querystring.unescape(PING_REGEX.exec(urlParts.pathname)[1]) host = querystring.unescape(PING_REGEX.exec(urlParts.pathname)[1])
require('child_process').exec("ping -w 1 -i 0.2 -c 3 #{host}", (err, stdout, stderr) -> require('child_process').exec("ping -w 1 -i 0.2 -c 3 #{host}", (err, stdout, stderr) ->
if err? if err
response.writeHead(404, {'Cache-Control' : 'no-cache'}) response.writeHead(404, {'Cache-Control' : 'no-cache'})
response.end() response.end(errorToString(err))
return return
response.writeHead(200, {'Content-Type' : 'text/plain', 'Cache-Control' : 'no-cache'}) response.writeHead(200, {'Content-Type' : 'text/plain', 'Cache-Control' : 'no-cache'})
response.end(stdout) response.end(stdout)
@@ -320,7 +375,7 @@ listener = (request, response) ->
apiFunctions.deleteDevice(deviceId, (err) -> apiFunctions.deleteDevice(deviceId, (err) ->
if err if err
response.writeHead(500) response.writeHead(500)
response.end(err.message) response.end(errorToString(err))
return return
response.writeHead(200) response.writeHead(200)
response.end() response.end()
@@ -343,7 +398,7 @@ listener = (request, response) ->
q = JSON.parse(urlParts.query.query) q = JSON.parse(urlParts.query.query)
catch err catch err
response.writeHead(400) response.writeHead(400)
response.end(err.toString()) response.end(errorToString(err))
return return
else else
q = {} q = {}
+13 -5
View File
@@ -294,11 +294,19 @@ exports.processDevicePreset = (deviceId, devicePreset, callback) ->
getObjectHash = (object) -> getObjectHash = (object) ->
return object._id if not object._keys? or object._keys.length == 0 if object._keys?.length
hash = '' keys = object._keys
for k in object._keys else
hash += "#{k}=#{object[k]}" keys = (k for k in Object.keys(object) when k[0] != '_')
return hash
keys.sort()
hash = []
for k in keys
hash.push(k)
hash.push(common.getParamValueFromPath(object, k))
return JSON.stringify(hash)
accumulateConfigurations = (presets, objects) -> accumulateConfigurations = (presets, objects) ->
+1 -1
View File
@@ -51,7 +51,7 @@ listener = (httpRequest, httpResponse) ->
) )
httpResponse.writeHead(500, {'Connection' : 'close'}) httpResponse.writeHead(500, {'Connection' : 'close'})
httpResponse.end() httpResponse.end("#{err.name}: #{err.message}")
catch err2 catch err2
util.error("#{new Date().toISOString()} - #{err2.stack}\n") util.error("#{new Date().toISOString()} - #{err2.stack}\n")
) )
+2 -2
View File
@@ -354,8 +354,8 @@ this.download = (task, methodResponse, callback) ->
this.customCommand = (task, methodResponse, callback) -> this.customCommand = (task, methodResponse, callback) ->
# TODO implement timeout # TODO implement timeout
customCommands.execute(task.device, task.command, (err, value) -> customCommands.execute(task.device, task.command, (err, value) ->
if err? if err
task.fault = err task.fault = {name : err.name, message : err.message}
callback(null, STATUS_FAULT) callback(null, STATUS_FAULT)
else else
commandName = task.command.split(' ', 2)[0] commandName = task.command.split(' ', 2)[0]
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "genieacs", "name": "genieacs",
"version": "1.0.4", "version": "1.0.5",
"description": "A blazing fast TR-069 auto configuration server (ACS) built with Node.js, Redis, and MongoDB", "description": "A blazing fast TR-069 auto configuration server (ACS) built with Node.js, Redis, and MongoDB",
"repository": { "repository": {
"type": "git", "type": "git",
@@ -12,7 +12,7 @@
"ACS" "ACS"
], ],
"author": "Zaid Abdulla", "author": "Zaid Abdulla",
"license": "AGPL3", "license": "AGPL-3.0",
"readmeFilename": "README.md", "readmeFilename": "README.md",
"preferGlobal": true, "preferGlobal": true,
"directories": { "directories": {