Complete implementation of ChangeDUState
This commit is contained in:
1 parent
716f2c6df3
commit
84de431872
4 files changed
+145
-17
No files matched your search
+43
@@ -361,6 +361,39 @@ async function transferComplete(sessionContext, rpc): Promise<void> {
|
||||
return writeResponse(sessionContext, res);
|
||||
}
|
||||
|
||||
async function duStateChangeComplete(sessionContext, rpc): Promise<void> {
|
||||
const { acsResponse, operation, fault } = await session.duStateChangeComplete(
|
||||
sessionContext,
|
||||
rpc.cpeRequest
|
||||
);
|
||||
|
||||
if (!operation) {
|
||||
logger.accessWarn({
|
||||
sessionContext: sessionContext,
|
||||
message: "Unrecognized command key",
|
||||
rpc: rpc,
|
||||
});
|
||||
}
|
||||
|
||||
if (fault) {
|
||||
Object.assign(sessionContext.retries, operation.retries);
|
||||
recordFault(
|
||||
sessionContext,
|
||||
fault,
|
||||
operation.provisions,
|
||||
operation.channels
|
||||
);
|
||||
}
|
||||
|
||||
const res = soap.response({
|
||||
id: rpc.id,
|
||||
acsResponse: acsResponse,
|
||||
cwmpVersion: sessionContext.cwmpVersion,
|
||||
});
|
||||
|
||||
return writeResponse(sessionContext, res);
|
||||
}
|
||||
|
||||
// Append provisions and remove duplicates
|
||||
function appendProvisions(original, toAppend): boolean {
|
||||
let modified = false;
|
||||
@@ -1239,6 +1272,16 @@ async function processRequest(
|
||||
cwmpVersion: sessionContext.cwmpVersion,
|
||||
});
|
||||
return writeResponse(sessionContext, res);
|
||||
} else if (rpc.cpeRequest.name === "DUStateChangeComplete") {
|
||||
if (sessionContext.state !== 1) return reportBadState(sessionContext);
|
||||
|
||||
logger.accessInfo({
|
||||
sessionContext: sessionContext,
|
||||
message: "CPE request",
|
||||
rpc: rpc,
|
||||
});
|
||||
|
||||
return duStateChangeComplete(sessionContext, rpc);
|
||||
} else {
|
||||
if (sessionContext.state !== 1 || rpc.cpeRequest.name === "Inform")
|
||||
return void reportBadState(sessionContext);
|
||||
|
||||
+95
-10
@@ -60,6 +60,7 @@ import {
|
||||
ChangeDUStateOperation,
|
||||
DownloadOperation,
|
||||
DUStateChangeCompleteRequest,
|
||||
ChangeDUState,
|
||||
} from "./types";
|
||||
import { getRequestOrigin } from "./forwarded";
|
||||
import * as logger from "./logger";
|
||||
@@ -452,8 +453,6 @@ export async function duStateChangeComplete(
|
||||
sessionContext.deviceData.attributes.revision = revision;
|
||||
const commandKey = rpcReq.commandKey;
|
||||
const operation = sessionContext.operations[commandKey];
|
||||
if (operation.name !== "ChangeDUState")
|
||||
throw new Error("Unexpected operation name");
|
||||
|
||||
if (!operation) {
|
||||
return {
|
||||
@@ -463,6 +462,21 @@ export async function duStateChangeComplete(
|
||||
};
|
||||
}
|
||||
|
||||
if (operation.name !== "ChangeDUState")
|
||||
throw new Error("Unexpected operation name");
|
||||
|
||||
if (operation.args.operations.length !== rpcReq.results.length) {
|
||||
return {
|
||||
acsResponse: { name: "DUStateChangeCompleteResponse" },
|
||||
operation: operation,
|
||||
fault: {
|
||||
code: "invalid_response",
|
||||
message: "Unexpected number of results in DUStateChangeComplete",
|
||||
timestamp: operation.timestamp,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
delete sessionContext.operations[commandKey];
|
||||
if (!sessionContext.operationsTouched) sessionContext.operationsTouched = {};
|
||||
sessionContext.operationsTouched[commandKey] = 1;
|
||||
@@ -1577,7 +1591,7 @@ export async function rpcRequest(
|
||||
if (index == null) {
|
||||
index = 0;
|
||||
for (const p of sessionContext.deviceData.paths.find(
|
||||
Path.parse("DUState.*"),
|
||||
Path.parse("DUStates.*"),
|
||||
false,
|
||||
true
|
||||
)) {
|
||||
@@ -1593,7 +1607,7 @@ export async function rpcRequest(
|
||||
|
||||
toClear = device.set(
|
||||
sessionContext.deviceData,
|
||||
Path.parse("DUState"),
|
||||
Path.parse("DUStates"),
|
||||
timestamp,
|
||||
{ object: [timestamp, 1], writable: [timestamp, 1] },
|
||||
toClear
|
||||
@@ -1601,7 +1615,7 @@ export async function rpcRequest(
|
||||
|
||||
toClear = device.set(
|
||||
sessionContext.deviceData,
|
||||
Path.parse(`DUState.${index}`),
|
||||
Path.parse(`DUStates.${index}`),
|
||||
timestamp,
|
||||
{ object: [timestamp, 1], writable: [timestamp, 1] },
|
||||
toClear
|
||||
@@ -1653,7 +1667,7 @@ export async function rpcRequest(
|
||||
for (const [k, v] of Object.entries(params)) {
|
||||
toClear = device.set(
|
||||
sessionContext.deviceData,
|
||||
Path.parse(`DUState.${index}.${k}`),
|
||||
Path.parse(`DUStates.${index}.${k}`),
|
||||
timestamp,
|
||||
{
|
||||
object: [timestamp, 0],
|
||||
@@ -1669,7 +1683,7 @@ export async function rpcRequest(
|
||||
|
||||
toClear = device.set(
|
||||
sessionContext.deviceData,
|
||||
Path.parse(`DUState.${index}.*`),
|
||||
Path.parse(`DUStates.${index}.*`),
|
||||
timestamp,
|
||||
null,
|
||||
toClear
|
||||
@@ -2014,6 +2028,7 @@ function generateSetRpcRequest(
|
||||
| FactoryReset
|
||||
| Reboot
|
||||
| Download
|
||||
| ChangeDUState
|
||||
) & { next?: string } {
|
||||
const syncState = sessionContext.syncState;
|
||||
if (!syncState) return null;
|
||||
@@ -2192,6 +2207,76 @@ function generateSetRpcRequest(
|
||||
}
|
||||
}
|
||||
|
||||
// ChangeDUState
|
||||
const duStateOps: ChangeDUState["operations"] = [];
|
||||
for (const [p, t] of syncState.duStatesChangeDUState) {
|
||||
const attrs = deviceData.attributes.get(p);
|
||||
if (attrs && attrs.value && t <= attrs.value[1][0]) continue;
|
||||
const urlAttrs = deviceData.attributes.get(
|
||||
deviceData.paths.get(p.slice(0, -1).concat(Path.parse("URL")))
|
||||
);
|
||||
const operationTypeAttrs = deviceData.attributes.get(
|
||||
deviceData.paths.get(p.slice(0, -1).concat(Path.parse("OperationType")))
|
||||
);
|
||||
const uuidAttrs = deviceData.attributes.get(
|
||||
deviceData.paths.get(p.slice(0, -1).concat(Path.parse("UUID")))
|
||||
);
|
||||
const executionEnvRefAttrs = deviceData.attributes.get(
|
||||
deviceData.paths.get(p.slice(0, -1).concat(Path.parse("ExecutionEnvRef")))
|
||||
);
|
||||
const versionAttrs = deviceData.attributes.get(
|
||||
deviceData.paths.get(p.slice(0, -1).concat(Path.parse("Version")))
|
||||
);
|
||||
const usernameAttrs = deviceData.attributes.get(
|
||||
deviceData.paths.get(p.slice(0, -1).concat(Path.parse("Username")))
|
||||
);
|
||||
const passwordAttrs = deviceData.attributes.get(
|
||||
deviceData.paths.get(p.slice(0, -1).concat(Path.parse("Password")))
|
||||
);
|
||||
|
||||
const operationType = operationTypeAttrs
|
||||
? (operationTypeAttrs.value[1][0] as string)
|
||||
: null;
|
||||
const url = urlAttrs ? (urlAttrs.value[1][0] as string) : null;
|
||||
const uuid = uuidAttrs ? (uuidAttrs.value[1][0] as string) : null;
|
||||
const executionEnvRef = executionEnvRefAttrs
|
||||
? (executionEnvRefAttrs.value[1][0] as string)
|
||||
: null;
|
||||
const version = versionAttrs ? (versionAttrs.value[1][0] as string) : null;
|
||||
const username = usernameAttrs
|
||||
? (usernameAttrs.value[1][0] as string)
|
||||
: null;
|
||||
const password = passwordAttrs
|
||||
? (passwordAttrs.value[1][0] as string)
|
||||
: null;
|
||||
|
||||
if (
|
||||
operationType !== "install" &&
|
||||
operationType !== "update" &&
|
||||
operationType !== "uninstall"
|
||||
)
|
||||
continue;
|
||||
|
||||
duStateOps.push({
|
||||
operationType: operationType,
|
||||
instance: p.segments[1] as string,
|
||||
url: url,
|
||||
uuid: uuid,
|
||||
executionEnvRef: executionEnvRef,
|
||||
version: version,
|
||||
username: username,
|
||||
password: password,
|
||||
});
|
||||
}
|
||||
|
||||
if (duStateOps.length) {
|
||||
return {
|
||||
name: "ChangeDUState",
|
||||
commandKey: generateRpcId(sessionContext),
|
||||
operations: duStateOps,
|
||||
};
|
||||
}
|
||||
|
||||
// Reboot
|
||||
if (syncState.reboot) {
|
||||
const p = sessionContext.deviceData.paths.get(Path.parse("Reboot"));
|
||||
@@ -2473,7 +2558,7 @@ function processDeclarations(
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "DUState":
|
||||
case "DUStates":
|
||||
if (
|
||||
currentPath.length === 3 &&
|
||||
currentPath.wildcard === 0 &&
|
||||
@@ -2955,7 +3040,7 @@ export async function rpcResponse(
|
||||
"FactoryReset",
|
||||
"VirtualParameters",
|
||||
"Downloads",
|
||||
"DUState",
|
||||
"DUStates",
|
||||
]) {
|
||||
const p = sessionContext.deviceData.paths.get(Path.parse(n));
|
||||
if (p && sessionContext.deviceData.attributes.has(p))
|
||||
@@ -3186,7 +3271,7 @@ export async function rpcResponse(
|
||||
for (const op of rpcReq.operations) {
|
||||
toClear = device.set(
|
||||
sessionContext.deviceData,
|
||||
Path.parse(`DuStates.${op.instance}.ChangeDUState`),
|
||||
Path.parse(`DUStates.${op.instance}.ChangeDUState`),
|
||||
timestamp + 1,
|
||||
{ value: [timestamp + 1, [sessionContext.timestamp, "xsd:dateTime"]] },
|
||||
toClear
|
||||
|
||||
+3
-3
@@ -788,10 +788,10 @@ function DUStateChangeComplete(xml: Element): DUStateChangeCompleteRequest {
|
||||
res.executionUnitRefList = cc.text;
|
||||
break;
|
||||
case "StartTime":
|
||||
res.startTime = Date.parse(c.text);
|
||||
if (c.text) res.startTime = Date.parse(c.text);
|
||||
break;
|
||||
case "CompleteTime":
|
||||
res.completeTime = Date.parse(c.text);
|
||||
if (c.text) res.completeTime = Date.parse(c.text);
|
||||
break;
|
||||
case "Fault":
|
||||
res.fault = {
|
||||
@@ -803,8 +803,8 @@ function DUStateChangeComplete(xml: Element): DUStateChangeCompleteRequest {
|
||||
};
|
||||
break;
|
||||
}
|
||||
results.push(res);
|
||||
}
|
||||
results.push(res);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -304,10 +304,10 @@ export interface ChangeDUState {
|
||||
instance: string;
|
||||
url: string;
|
||||
uuid: string;
|
||||
version?: string;
|
||||
executionEnvRef?: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
version: string;
|
||||
executionEnvRef: string;
|
||||
username: string;
|
||||
password: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user