diff --git a/lib/cache.coffee b/lib/cache.coffee index 58e1755..4511530 100644 --- a/lib/cache.coffee +++ b/lib/cache.coffee @@ -136,7 +136,7 @@ refresh = (callback) -> for c in preset.configurations switch c.type when 'age' - _provisions.push(['refresh', c.name, c.age * -1000]) + _provisions.push(['refresh', c.name, c.age]) when 'value' _provisions.push(['value', c.name, c.value]) when 'add_tag' diff --git a/lib/cwmp.coffee b/lib/cwmp.coffee index 1f6a01b..538e650 100644 --- a/lib/cwmp.coffee +++ b/lib/cwmp.coffee @@ -41,7 +41,6 @@ util = require 'util' zlib = require 'zlib' crypto = require 'crypto' -mongodb = require 'mongodb' config = require './config' common = require './common' @@ -341,8 +340,8 @@ nextRpc = (currentRequest) -> if fault for channel of currentRequest.sessionData.channels - if channel.startsWith('_task_') - taskId = channel.slice(6) + if channel.startsWith('task_') + taskId = channel.slice(5) for t, j in currentRequest.sessionData.tasks if t._id == taskId currentRequest.sessionData.tasks.splice(j, 1) @@ -362,12 +361,12 @@ nextRpc = (currentRequest) -> currentRequest.sessionData.faultsTouched ?= {} currentRequest.sessionData.faultsTouched[channel] = true - for p in currentRequest.sessionData.provisions - if p[0] == '_task' + if channel.startsWith('task_') + taskId = channel.slice(5) currentRequest.sessionData.doneTasks ?= [] - currentRequest.sessionData.doneTasks.push(p[1]) + currentRequest.sessionData.doneTasks.push(taskId) for t, j in currentRequest.sessionData.tasks - if String(t._id) == p[1] + if t._id == taskId currentRequest.sessionData.tasks.splice(j, 1) break @@ -383,22 +382,25 @@ nextRpc = (currentRequest) -> switch task.name when 'getParameterValues' - session.addProvisions(currentRequest.sessionData, "_task_#{task._id}", [['_task', task._id, 'getParameterValues'].concat(task.parameterNames)]) + for p in task.parameterNames + session.addProvisions(currentRequest.sessionData, "task_#{task._id}", + [['refresh', p]]) when 'setParameterValues' - t = ['_task', task._id, 'setParameterValues'] for p in task.parameterValues - t.push(p[0]) - t.push(p[1]) - t.push(p[2] ? '') - session.addProvisions(currentRequest.sessionData, "_task_#{task._id}", [t]) + session.addProvisions(currentRequest.sessionData, "task_#{task._id}", + [['value', p[0], p[1]]]) when 'refreshObject' - session.addProvisions(currentRequest.sessionData, "_task_#{task._id}", [['_task', task._id, 'refreshObject', task.objectName]]) + session.addProvisions(currentRequest.sessionData, "task_#{task._id}", + [['refresh', task.objectName]]) when 'reboot' - session.addProvisions(currentRequest.sessionData, "_task_#{task._id}", [['_task', task._id, 'reboot']]) + session.addProvisions(currentRequest.sessionData, "task_#{task._id}", + [['reboot']]) when 'factoryReset' - session.addProvisions(currentRequest.sessionData, "_task_#{task._id}", [['_task', task._id, 'factoryReset']]) + session.addProvisions(currentRequest.sessionData, "task_#{task._id}", + [['reset']]) when 'download' - session.addProvisions(currentRequest.sessionData, "_task_#{task._id}", [['_task', task._id, 'download', task.fileType, task.fileName, task.targetFileName]]) + session.addProvisions(currentRequest.sessionData, "task_#{task._id}", + [['download', task.fileType, task.fileName, task.targetFileName]]) else return throwError(new Error('Task name not recognized'), currentRequest.httpResponse) if err @@ -643,8 +645,8 @@ listener = (httpRequest, httpResponse) -> if fault for channel of currentRequest.sessionData.channels - if channel.startsWith('_task_') - taskId = channel.slice(6) + if channel.startsWith('task_') + taskId = channel.slice(5) for t, j in currentRequest.sessionData.tasks if t._id == taskId currentRequest.sessionData.tasks.splice(j, 1) diff --git a/lib/default-provisions.js b/lib/default-provisions.js new file mode 100644 index 0000000..cabfc5f --- /dev/null +++ b/lib/default-provisions.js @@ -0,0 +1,87 @@ +/** + * Copyright 2013-2016 Zaid Abdulla + * + * GenieACS is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * GenieACS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with GenieACS. If not, see . + */ +"use strict"; + +const config = require("./config"); +const common = require("./common"); + +const MAX_DEPTH = config.get("MAX_DEPTH"); + + +function refresh(sessionData, provision, declarations, startRevision, endRevision) { + let path = common.parsePath(provision[1]).slice(); + let l = path.length; + path.length = MAX_DEPTH; + path.fill("*", l); + let every = 1000 * (provision[2] || 1); + let t = Math.trunc(sessionData.timestamp / every) * every; + + for (let i = l; i < path.length; ++ i) + declarations.push([path.slice(0, i), t, {object: 1, writable: 1, value: t}]); + + return true; +} + + +function value(sessionData, provision, declarations, startRevision, endRevision) { + let path = common.parsePath(provision[1]); + declarations.push([path, 1, {value: 1}, null, {value: [provision[2]]}]); + + return true; +} + + +function tag(sessionData, provision, declarations, startRevision, endRevision) { + let path = ["Tags", provision[1]]; + declarations.push([path, 1, {value: 1}, null, {value: [provision[2]]}]); + + return true; +} + + +function reboot(sessionData, provision, declarations, startRevision, endRevision) { + declarations.push([["Reboot"], 1, {value: 1}, null, {value: [sessionData.timestamp]}]); + + return true; +} + + +function reset(sessionData, provision, declarations, startRevision, endRevision) { + declarations.push([["FactoryReset"], 1, {value: 1}, null, {value: [sessionData.timestamp]}]); + + return true; +} + + +function download(sessionData, provision, declarations, startRevision, endRevision) { + let alias = ["FileType", provision[1] || "", "FileName", provision[2] || "", + "TargetFileName", provision[3] || ""]; + + declarations.push([["Downloads", alias], 1, {}, 1]); + declarations.push([["Downloads", alias, "Download"], 1, {value: 1}, null, + {value: [sessionData.timestamp]}]); + + return true; +} + + +exports.refresh = refresh; +exports.value = value; +exports.tag = tag; +exports.reboot = reboot; +exports.reset = reset; +exports.download = download; diff --git a/lib/session.coffee b/lib/session.coffee index 110332e..3917ade 100644 --- a/lib/session.coffee +++ b/lib/session.coffee @@ -24,6 +24,7 @@ cache = require './cache' PathSet = require './path-set' VersionedMap = require './versioned-map' InstanceSet = require './instance-set' +defaultProvisions = require './default-provisions' initDeviceData = () -> @@ -323,50 +324,8 @@ runProvisions = (sessionData, provisions, startRevision, endRevision, callback) counter = 1 for provision in provisions if not sessionData.cache.provisions[provision[0]]? - switch provision[0] - when 'refresh' - path = common.parsePath(provision[1]).slice() - l = path.length - path.length = config.get('MAX_DEPTH', sessionData.deviceId) - path.fill('*', l) - t = provision[2] - t += sessionData.timestamp if t <= 0 - - for i in [l...path.length] by 1 - p = common.addPathMeta(path.slice(0, i)) - allDeclarations.push([p, t, {object: 1, writable: 1, value: t}]) - when 'value' - allDeclarations.push([common.parsePath(provision[1]), 1, {value: 1}, null, {value: [provision[2]]}]) - when 'tag' - allDeclarations.push([['Tags', provision[1]], 1, {value: 1}, null, {value: [provision[2], 'xsd:boolean']}]) - when '_task' - # A special provision for tasks compatibility - switch provision[2] - when 'getParameterValues' - for i in [3...provision.length] by 1 - allDeclarations.push([common.parsePath(provision[i]), 1, {value: sessionData.timestamp}]) - when 'setParameterValues' - for i in [3...provision.length] by 3 - v = if provision[i + 2] then [provision[i + 1], provision[i + 2]] else [provision[i + 1]] - allDeclarations.push([common.parsePath(provision[i]), 1, {value: 1}, null, {value: v}]) - when 'refreshObject' - path = common.parsePath(provision[3]).slice() - l = path.length - path.length = config.get('MAX_DEPTH', sessionData.deviceId) - path.fill('*', l) - for i in [l...path.length] by 1 - p = common.addPathMeta(path.slice(0, i)) - allDeclarations.push([p, sessionData.timestamp, {object: 1, writable: 1, value: sessionData.timestamp}]) - when 'reboot' - allDeclarations.push([['Reboot'], 1, {value: 1}, null, {value: [sessionData.timestamp]}]) - when 'factoryReset' - allDeclarations.push([['FactoryReset'], 1, {value: 1}, null, {value: [sessionData.timestamp]}]) - when 'download' - alias = "[FileType:#{JSON.stringify(provision[3] or '')},FileName:#{JSON.stringify(provision[4] or '')},TargetFileName:#{JSON.stringify(provision[5] or '')}]" - allDeclarations.push([common.parsePath("Downloads.#{alias}"), - 1, {}, 1, {}]) - allDeclarations.push([common.parsePath("Downloads.#{alias}.Download"), - 1, {value: 1}, null, {value: [sessionData.timestamp]}]) + if defaultProvisions[provision[0]] + done = defaultProvisions[provision[0]](sessionData, provision, allDeclarations, startRevision, endRevision) and done continue ++ counter