Files
adam-acs/app/protocol/cwmp-1-1.ts
T
Kevin L'Hereec f3eb8e1650 feat: restore strong typing on TR-069/CWMP protocol layer
- Copy cwmp-1-0..4.ts source classes from cwmp-connector (papaye) into
  app/protocol/ as local files (ts-nocheck, external dependency)
- Add soap_envelope.ts: SoapEnvelope, SoapEnvelopeHeader, CwmpID, NAMESPACES
- Add tr069_types.ts: re-exports all CWMP classes + CwmpMessage discriminated
  union + typed task payload interfaces (CWMPTaskType, CWMPTaskPayload, etc.)
- Rewrite cwmp_message_builder.ts to use class-based builders instead of raw
  XML template strings; add transferCompleteResponse() and soapFault()
- soap.ts: extractCwmpMessage returns CwmpMessage union, adds runtime allowlist
  guard against unknown CWMP method names from CPE
- cwmp_middleware.ts: envelope typed SoapEnvelope|null, message CwmpMessage|null
- cwmp_controller.ts: handleInform(informData: Inform), remove any, migrate
  TransferComplete and fault to new builder path, drop buildSoapEnvelope import
- task_queue.ts: CWMPTask.type → CWMPTaskType literal union, payload →
  CWMPTaskPayload, result → CWMPTaskResultData
- device_action_executor.ts: GPV/GPN/GPA responses typed, no more any
- main_state_machine.ts: DeviceContext.message.data → CWMPTaskResultData,
  organizeParameters receives ParameterInfoStruct[] directly
- device.ts: tmpParamValues typed ParameterValueStruct[], organizeParameters
  signature updated, updateFromValues typed
- device_id.ts: fromInform typed with DeviceIdStruct
- soap_envelope.ts: remove unconditional <cwmp:noMoreRequests> header
  (CPE→ACS only per TR-069 §3.7.1.4)
2026-07-20 15:25:26 +02:00

221 lines
7.4 KiB
TypeScript

// @ts-nocheck — fichier copié de cwmp-connector (papaye)
import { Cwmp_1_0, FaultCodeType } from './cwmp-1-0.js'
/**
* CWMP Version 1.1 Protocol Classes
*
* This version extends CWMP 1.0 with additional features:
* - Additional fault codes (9014-9019)
* - New event code: "10 AUTONOMOUS TRANSFER COMPLETE"
* - New messages: GetAllQueuedTransfers, AutonomousTransferComplete
* - AllQueuedTransferStruct and AllTransferList types
*/
export class Cwmp_1_1 extends Cwmp_1_0 {
public '@class' = '.Cwmp_1_1'
public GetAllQueuedTransfers?: GetAllQueuedTransfers
public GetAllQueuedTransfersResponse?: GetAllQueuedTransfersResponse
public AutonomousTransferComplete?: AutonomousTransferComplete
public AutonomousTransferCompleteResponse?: AutonomousTransferCompleteResponse
constructor(props: any = {}) {
super(props)
this.GetAllQueuedTransfers = props.GetAllQueuedTransfers ? new GetAllQueuedTransfers(props.GetAllQueuedTransfers) : undefined
this.GetAllQueuedTransfersResponse = props.GetAllQueuedTransfersResponse ? new GetAllQueuedTransfersResponse(props.GetAllQueuedTransfersResponse) : undefined
this.AutonomousTransferComplete = props.AutonomousTransferComplete ? new AutonomousTransferComplete(props.AutonomousTransferComplete) : undefined
this.AutonomousTransferCompleteResponse = props.AutonomousTransferCompleteResponse ? new AutonomousTransferCompleteResponse(props.AutonomousTransferCompleteResponse) : undefined
}
}
// Extended fault codes for CWMP 1.1
export enum FaultCodeType_1_1 {
// All codes from 1.0
MethodNotSupported = 9000,
RequestDenied = 9001,
InternalError = 9002,
InvalidArguments = 9003,
ResourcesExceeded = 9004,
InvalidParameterName = 9005,
InvalidParameterType = 9006,
InvalidParameterValue = 9007,
NonWritableParameter = 9008,
NotificationRequestRejected = 9009,
DownloadFailure = 9010,
UploadFailure = 9011,
FileTransferServerAuthFailure = 9012,
UnsupportedProtocolForFileTransfer = 9013,
// New codes in 1.1
DownloadFailureUnableToJoinMulticastGroup = 9014,
DownloadFailureUnableToContactFileServer = 9015,
DownloadFailureUnableToAccessFile = 9016,
DownloadFailureUnableToCompleteDownload = 9017,
DownloadFailureFileCorrupted = 9018,
DownloadFailureFileAuthenticationFailure = 9019,
// Future expansion fault codes
FutureExpansionMin = 9020,
FutureExpansionMax = 9799,
// CPE Vendor fault codes (range)
VendorFaultCodeMin = 9800,
VendorFaultCodeMax = 9899,
// ACS fault codes
ACSMethodNotSupported = 8000,
ACSRequestDenied = 8001,
ACSInternalError = 8002,
ACSInvalidArguments = 8003,
ACSResourcesExceeded = 8004,
ACSRetryRequest = 8005,
// ACS Future expansion fault codes
ACSFutureExpansionMin = 8006,
ACSFutureExpansionMax = 8799,
// ACS Vendor fault codes (range)
ACSVendorFaultCodeMin = 8800,
ACSVendorFaultCodeMax = 8899,
}
// Extended EventCode enum for CWMP 1.1
export enum EventCode_1_1 {
BOOTSTRAP = '0 BOOTSTRAP',
BOOT = '1 BOOT',
PERIODIC = '2 PERIODIC',
SCHEDULED = '3 SCHEDULED',
VALUE_CHANGE = '4 VALUE CHANGE',
KICKED = '5 KICKED',
CONNECTION_REQUEST = '6 CONNECTION REQUEST',
TRANSFER_COMPLETE = '7 TRANSFER COMPLETE',
DIAGNOSTICS_COMPLETE = '8 DIAGNOSTICS COMPLETE',
REQUEST_DOWNLOAD = '9 REQUEST DOWNLOAD',
AUTONOMOUS_TRANSFER_COMPLETE = '10 AUTONOMOUS TRANSFER COMPLETE', // New in 1.1
REBOOT = 'M Reboot',
SCHEDULE_INFORM = 'M ScheduleInform',
DOWNLOAD = 'M Download',
UPLOAD = 'M Upload',
X_METHOD = 'M X_',
X_PATTERN = 'X [0-9A-F]{6} .*',
}
export class AllQueuedTransferStruct {
public '@class' = '.AllQueuedTransferStruct'
public CommandKey: string
public State: number
public IsDownload: boolean
public FileType: string
public FileSize: number
public TargetFileName: string
constructor(props: any = {}) {
this.CommandKey = props.CommandKey || ''
this.State = props.State || 1
this.IsDownload = props.IsDownload || false
this.FileType = props.FileType || ''
this.FileSize = props.FileSize || 0
this.TargetFileName = props.TargetFileName || ''
}
}
export class AllTransferList {
public '@class' = '.AllTransferList'
public AllQueuedTransferStruct: AllQueuedTransferStruct[] = []
constructor(props: any = {}) {
this.AllQueuedTransferStruct = (props.AllQueuedTransferStruct || []).map((item: any) => new AllQueuedTransferStruct(item))
}
}
export class GetAllQueuedTransfers {
public '@class' = '.GetAllQueuedTransfers'
constructor(props: any = {}) {}
getXml() {
return `<cwmp:GetAllQueuedTransfers></cwmp:GetAllQueuedTransfers>`
}
}
export class GetAllQueuedTransfersResponse {
public '@class' = '.GetAllQueuedTransfersResponse'
public TransferList?: AllTransferList
constructor(props: any = {}) {
this.TransferList = props.TransferList ? new AllTransferList(props.TransferList) : undefined
}
getXml() {
const items = this.TransferList?.AllQueuedTransferStruct || []
const listXml = items
.map(
(t) => `
<AllQueuedTransferStruct>
<CommandKey>${t.CommandKey}</CommandKey>
<State>${t.State}</State>
<IsDownload>${t.IsDownload ? 1 : 0}</IsDownload>
<FileType>${t.FileType}</FileType>
<FileSize>${t.FileSize}</FileSize>
<TargetFileName>${t.TargetFileName}</TargetFileName>
</AllQueuedTransferStruct>`
)
.join('')
return `<cwmp:GetAllQueuedTransfersResponse>
<TransferList soap-enc:arrayType="cwmp:AllQueuedTransferStruct[${items.length}]">
${listXml}
</TransferList>
</cwmp:GetAllQueuedTransfersResponse>`
}
}
export class AutonomousTransferComplete {
public '@class' = '.AutonomousTransferComplete'
public AnnounceURL: string
public TransferURL: string
public IsDownload: boolean
public FileType: string
public FileSize: number
public TargetFileName: string
public FaultStruct: any // Reusing FaultStruct from base
public StartTime: Date
public CompleteTime: Date
constructor(props: any = {}) {
this.AnnounceURL = props.AnnounceURL || ''
this.TransferURL = props.TransferURL || ''
this.IsDownload = props.IsDownload || false
this.FileType = props.FileType || ''
this.FileSize = props.FileSize || 0
this.TargetFileName = props.TargetFileName || ''
this.FaultStruct = props.FaultStruct
this.StartTime = props.StartTime ? new Date(props.StartTime) : new Date()
this.CompleteTime = props.CompleteTime ? new Date(props.CompleteTime) : new Date()
}
getXml() {
const fault = this.FaultStruct
? `<FaultStruct><FaultCode>${this.FaultStruct.FaultCode ?? 0}</FaultCode><FaultString>${this.FaultStruct.FaultString || ''}</FaultString></FaultStruct>`
: ''
return `<cwmp:AutonomousTransferComplete>
<AnnounceURL>${this.AnnounceURL}</AnnounceURL>
<TransferURL>${this.TransferURL}</TransferURL>
<IsDownload>${this.IsDownload ? 1 : 0}</IsDownload>
<FileType>${this.FileType}</FileType>
<FileSize>${this.FileSize}</FileSize>
<TargetFileName>${this.TargetFileName}</TargetFileName>
${fault}
<StartTime>${this.StartTime.toISOString()}</StartTime>
<CompleteTime>${this.CompleteTime.toISOString()}</CompleteTime>
</cwmp:AutonomousTransferComplete>`
}
}
export class AutonomousTransferCompleteResponse {
public '@class' = '.AutonomousTransferCompleteResponse'
constructor(props: any = {}) {}
getXml() {
return '<cwmp:AutonomousTransferCompleteResponse/>'
}
}