From 39a5ff8a9a6b177179fcc989a34c7212848748d6 Mon Sep 17 00:00:00 2001 From: Zaid Abdulla Date: Fri, 22 Feb 2013 22:37:51 +0300 Subject: [PATCH] Firmware upgrade now functional --- acs.coffee | 61 ++++++++++--------- config.coffee | 1 + db.coffee | 4 ++ tasks.coffee | 162 +++++++++++++++++++++++++++----------------------- tr-069.coffee | 2 +- 5 files changed, 123 insertions(+), 107 deletions(-) diff --git a/acs.coffee b/acs.coffee index 5097ab9..b9930a6 100644 --- a/acs.coffee +++ b/acs.coffee @@ -94,38 +94,37 @@ updateDevice = (currentRequest, actions, callback) -> runTask = (currentRequest, task, methodResponse) -> - cwmpResponse = {} - deviceUpdates = {} - status = tasks.task(task, methodResponse, cwmpResponse, deviceUpdates) + tasks.task(task, methodResponse, (err, status, cwmpResponse, deviceUpdates) -> + # TODO handle error + updateDevice(currentRequest, deviceUpdates) - updateDevice(currentRequest, deviceUpdates) - - switch status - when tasks.STATUS_FINISHED - db.memcached.del(String(task._id)) - db.tasksCollection.remove({'_id' : mongodb.ObjectID(String(task._id))}, {safe: true}, (err, removed) -> - util.log("#{currentRequest.deviceId}: Completed task #{task.name}(#{task._id})") - nextTask(currentRequest) - ) - when tasks.STATUS_FAULT - util.log("#{currentRequest.deviceId}: Fault response for task #{task._id}") - db.saveTask(task, (err) -> - # Faulty task. No more work to do until task is deleted. - res = tr069.response(null, cwmpResponse) - writeResponse(currentRequest, res) - ) - when tasks.STATUS_PENDING - db.saveTask(task, (err) -> - # task expects CPE confirmation later - nextTask(currentRequest) - ) - when tasks.STATUS_STARTED - db.updateTask(task, (err) -> - res = tr069.response(task._id, cwmpResponse) - writeResponse(currentRequest, res) - ) - else - throw Error('Unknown task status') + switch status + when tasks.STATUS_FINISHED + db.memcached.del(String(task._id)) + db.tasksCollection.remove({'_id' : mongodb.ObjectID(String(task._id))}, {safe: true}, (err, removed) -> + util.log("#{currentRequest.deviceId}: Completed task #{task.name}(#{task._id})") + nextTask(currentRequest) + ) + when tasks.STATUS_FAULT + util.log("#{currentRequest.deviceId}: Fault response for task #{task._id}") + db.saveTask(task, (err) -> + # Faulty task. No more work to do until task is deleted. + res = tr069.response(null, cwmpResponse) + writeResponse(currentRequest, res) + ) + when tasks.STATUS_PENDING + db.saveTask(task, (err) -> + # task expects CPE confirmation later + nextTask(currentRequest) + ) + when tasks.STATUS_STARTED + db.updateTask(task, (err) -> + res = tr069.response(task._id, cwmpResponse) + writeResponse(currentRequest, res) + ) + else + throw Error('Unknown task status') + ) nextTask = (currentRequest) -> diff --git a/config.coffee b/config.coffee index 6c10c0e..7d12e23 100644 --- a/config.coffee +++ b/config.coffee @@ -7,6 +7,7 @@ exports.API_PORT = 7557 exports.API_INTERFACE = '0.0.0.0' exports.FILES_PORT = 7567 exports.FILES_INTERFACE = '0.0.0.0' +exports.FILES_IP = '172.240.21.2' # Used when sending download requests to devices exports.CACHE_DURATION = 60 # in seconds exports.PRESETS_CACHE_DURATION = 86400 exports.PRESETS_TIME_PADDING = 1 diff --git a/db.coffee b/db.coffee index 0b190af..a3de1a1 100644 --- a/db.coffee +++ b/db.coffee @@ -33,6 +33,10 @@ db.open( (err, db) -> db.collection('presets', (err, collection) -> exports.presetsCollection = presetsCollection = collection ) + + db.collection('fs.files', (err, collection) -> + exports.filesCollection = filesCollection = collection + ) ) diff --git a/tasks.coffee b/tasks.coffee index e362539..337939a 100644 --- a/tasks.coffee +++ b/tasks.coffee @@ -1,4 +1,7 @@ +config = require './config' common = require './common' +db = require './db' +mongodb = require 'mongodb' BATCH_SIZE = 16 exports.STATUS_QUEUED = STATUS_QUEUED = 0 @@ -8,60 +11,64 @@ exports.STATUS_FAULT = STATUS_FAULT = 3 exports.STATUS_FINISHED = STATUS_FINISHED = 4 -this.init = (task, methodResponse, cwmpResponse, deviceUpdates) -> +this.init = (task, methodResponse, callback) -> if not task.subtask? - task.subtask = {'name' : 'getParameterNames', 'parameterPath' : '', 'nextLevel' : false} + task.subtask = {name : 'getParameterNames', parameterPath : '', nextLevel : false} if task.subtask.name == 'getParameterNames' if methodResponse.faultcode? task.fault = methodResponse - return STATUS_FAULT + callback(null, STATUS_FAULT) + return - status = this.getParameterNames(task.subtask, methodResponse, cwmpResponse, deviceUpdates) - if status is STATUS_FINISHED - parameterNames = [] - for p in deviceUpdates.parameterNames - if not common.endsWith(p[0], '.') - parameterNames.push(p[0]) - task.subtask = {'name' : 'getParameterValues', 'parameterNames' : parameterNames} - else if status != STATUS_STARTED - throw Error('Unexpected subtask status') - - if task.subtask.name == 'getParameterValues' + this.getParameterNames(task.subtask, methodResponse, (err, status, cwmpResponse, deviceUpdates) => + if status is STATUS_FINISHED + parameterNames = [] + for p in deviceUpdates.parameterNames + if not common.endsWith(p[0], '.') + parameterNames.push(p[0]) + task.subtask = {name : 'getParameterValues', parameterNames : parameterNames} + this.getParameterValues(task.subtask, {}, (err, status, cwmpResponse, deviceUpdates) -> + callback(err, status, cwmpResponse, deviceUpdates) + ) + else if status is STATUS_STARTED + callback(err, STATUS_STARTED, cwmpResponse, deviceUpdates) + else + throw Error('Unexpected subtask status') + ) + else if task.subtask.name == 'getParameterValues' if methodResponse.faultcode? # Ignore GetParameterValues errors. A workaround for the crappy Seewon devices. - status = this.getParameterValues(task.subtask, {parameterList : {}}, cwmpResponse, deviceUpdates) - else - status = this.getParameterValues(task.subtask, methodResponse, cwmpResponse, deviceUpdates) - if status is STATUS_FINISHED - return STATUS_FINISHED - else if status isnt STATUS_STARTED - throw Error('Unexpected subtask status') - - return STATUS_STARTED + methodResponse = {parameterList : {}} + this.getParameterValues(task.subtask, methodResponse, (err, status, cwmpResponse, deviceUpdates) -> + callback(err, status, cwmpResponse, deviceUpdates) + ) + else + throw Error('Unexpected subtask name') -this.getParameterNames = (task, methodResponse, cwmpResponse, deviceUpdates) -> +this.getParameterNames = (task, methodResponse, callback) -> if methodResponse.faultcode? task.fault = methodResponse - return STATUS_FAULT + callback(null, STATUS_FAULT) + return if methodResponse.type is 'GetParameterNamesResponse' - deviceUpdates.parameterNames = methodResponse.parameterList - return STATUS_FINISHED - - cwmpResponse.methodRequest = { - type : 'GetParameterNames', - parameterPath : task.parameterPath, - nextLevel : if task.nextLevel? then task.nextLevel else false - } - return STATUS_STARTED + callback(null, STATUS_FINISHED, null, {parameterNames : methodResponse.parameterList}) + else + methodRequest = { + type : 'GetParameterNames', + parameterPath : task.parameterPath, + nextLevel : if task.nextLevel? then task.nextLevel else false + } + callback(null, STATUS_STARTED, {methodRequest : methodRequest}) -this.getParameterValues = (task, methodResponse, cwmpResponse, deviceUpdates) -> +this.getParameterValues = (task, methodResponse, callback) -> if methodResponse.faultcode? task.fault = methodResponse - return STATUS_FAULT + callback(null, STATUS_FAULT) + return if not task.currentIndex? task.currentIndex = 0 @@ -72,23 +79,23 @@ this.getParameterValues = (task, methodResponse, cwmpResponse, deviceUpdates) -> names = task.parameterNames.slice(task.currentIndex, task.nextIndex) if methodResponse.type is 'GetParameterValuesResponse' - deviceUpdates.parameterValues = methodResponse.parameterList + deviceUpdates = {parameterValues : methodResponse.parameterList} if names.length == 0 - return STATUS_FINISHED - - cwmpResponse.methodRequest = { - type : 'GetParameterValues', - parameterNames : names - } - - return STATUS_STARTED + callback(null, STATUS_FINISHED, null, deviceUpdates) + else + methodRequest = { + type : 'GetParameterValues', + parameterNames : names + } + callback(null, STATUS_STARTED, {methodRequest : methodRequest}, deviceUpdates) -this.setParameterValues = (task, methodResponse, cwmpResponse, deviceUpdates) -> +this.setParameterValues = (task, methodResponse, callback) -> if methodResponse.faultcode? task.fault = methodResponse - return STATUS_FAULT + callback(null, STATUS_FAULT) + return if not task.currentIndex? task.currentIndex = 0 @@ -100,47 +107,52 @@ this.setParameterValues = (task, methodResponse, cwmpResponse, deviceUpdates) -> values = task.parameterValues.slice(task.currentIndex, task.nextIndex) if prevValues? - deviceUpdates.parameterValues = prevValues + deviceUpdates = {parameterValues : prevValues} if values.length == 0 - return STATUS_FINISHED - - cwmpResponse.methodRequest = { - type : 'SetParameterValues', - parameterList : values - } - return STATUS_STARTED + callback(null, STATUS_FINISHED, null, deviceUpdates) + else + callback(null, STATUS_STARTED, {methodRequest : {type : 'SetParameterValues', parameterList : values}}, deviceUpdates) -this.reboot = (task, methodResponse, cwmpResponse, deviceUpdates) -> +this.reboot = (task, methodResponse, callback) -> if methodResponse.faultcode? task.fault = methodResponse - return STATUS_FAULT - + callback(null, STATUS_FAULT) + return + if methodResponse.type isnt 'RebootResponse' - cwmpResponse.methodRequest = { - type : 'Reboot' - } - return STATUS_STARTED - - return STATUS_FINISHED + callback(null, STATUS_STARTED, {methodRequest : {type : 'Reboot'}}) + else + callback(null, STATUS_FINISHED) -this.download = (task, methodResponse, cwmpResponse, deviceUpdates) -> +this.download = (task, methodResponse, callback) -> if methodResponse.faultcode? task.fault = methodResponse - return STATUS_FAULT + callback(null, STATUS_FAULT) + return if methodResponse.type isnt 'DownloadResponse' - cwmpResponse.methodRequest = { - type : 'Download', - fileType : task.fileType, - url : task.url - } - return STATUS_STARTED + db.filesCollection.findOne({_id : mongodb.ObjectID(task.file)}, (err, file) -> + if not file? + callback('File not found') + return + else if err? + callback(err) + return - return STATUS_FINISHED + methodRequest = { + type : 'Download', + fileType : '1 Firmware Upgrade Image', + fileSize : file.length, + url : "http://#{config.FILES_IP}:#{config.FILES_PORT}/#{file.filename}" + } + callback(null, STATUS_STARTED, {methodRequest : methodRequest}) + ) + else + callback(null, STATUS_FINISHED) -exports.task = (task, methodResponse, cwmpResponse, deviceUpdates) -> - return this[task.name](task, methodResponse, cwmpResponse, deviceUpdates) +exports.task = (task, methodResponse, callback) -> + this[task.name](task, methodResponse, callback) diff --git a/tr-069.coffee b/tr-069.coffee index 94ae9b5..cb4267d 100644 --- a/tr-069.coffee +++ b/tr-069.coffee @@ -222,7 +222,7 @@ exports.response = (id, cwmpResponse, cookies = null) -> if cookies? and Object.keys(cookies).length > 0 headers['Set-Cookie'] = cookiesToStr(cookies) - if cwmpResponse is null or Object.keys(cwmpResponse).length == 0 + if not cwmpResponse? or Object.keys(cwmpResponse).length == 0 #console.log '>>> EMPTY RESPONSE' # send empty response headers['Content-Length'] = 0