- 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)
200 lines
7.0 KiB
TypeScript
200 lines
7.0 KiB
TypeScript
/**
|
|
* Classes SOAP Envelope (extraites de cwmp-connector/src/protocol/soap.ts)
|
|
*
|
|
* Séparées de soap.ts (le module de parsing d'adam-acs) pour éviter les conflits de nom.
|
|
*/
|
|
import { Cwmp_1_0 } from './cwmp-1-0.js'
|
|
import { Cwmp_1_1 } from './cwmp-1-1.js'
|
|
import { Cwmp_1_2 } from './cwmp-1-2.js'
|
|
import { Cwmp_1_3, SessionTimeout } from './cwmp-1-3.js'
|
|
import { Cwmp_1_4, SupportedCWMPVersions, UseCWMPVersion } from './cwmp-1-4.js'
|
|
|
|
type NamespaceDescriptor = {
|
|
SoapEnc: string
|
|
SoapEnv: string
|
|
Xsd: string
|
|
Xsi: string
|
|
Cwmp: string
|
|
}
|
|
|
|
export const NAMESPACES: Record<string, NamespaceDescriptor> = {
|
|
'1.0': {
|
|
SoapEnc: 'http://schemas.xmlsoap.org/soap/encoding/',
|
|
SoapEnv: 'http://schemas.xmlsoap.org/soap/envelope/',
|
|
Xsd: 'http://www.w3.org/2001/XMLSchema',
|
|
Xsi: 'http://www.w3.org/2001/XMLSchema-instance',
|
|
Cwmp: 'urn:dslforum-org:cwmp-1-0',
|
|
},
|
|
'1.1': {
|
|
SoapEnc: 'http://schemas.xmlsoap.org/soap/encoding/',
|
|
SoapEnv: 'http://schemas.xmlsoap.org/soap/envelope/',
|
|
Xsd: 'http://www.w3.org/2001/XMLSchema',
|
|
Xsi: 'http://www.w3.org/2001/XMLSchema-instance',
|
|
Cwmp: 'urn:dslforum-org:cwmp-1-1',
|
|
},
|
|
'1.2': {
|
|
SoapEnc: 'http://schemas.xmlsoap.org/soap/encoding/',
|
|
SoapEnv: 'http://schemas.xmlsoap.org/soap/envelope/',
|
|
Xsd: 'http://www.w3.org/2001/XMLSchema',
|
|
Xsi: 'http://www.w3.org/2001/XMLSchema-instance',
|
|
Cwmp: 'urn:dslforum-org:cwmp-1-2',
|
|
},
|
|
'1.3': {
|
|
SoapEnc: 'http://schemas.xmlsoap.org/soap/encoding/',
|
|
SoapEnv: 'http://schemas.xmlsoap.org/soap/envelope/',
|
|
Xsd: 'http://www.w3.org/2001/XMLSchema',
|
|
Xsi: 'http://www.w3.org/2001/XMLSchema-instance',
|
|
Cwmp: 'urn:dslforum-org:cwmp-1-3',
|
|
},
|
|
'1.4': {
|
|
SoapEnc: 'http://schemas.xmlsoap.org/soap/encoding/',
|
|
SoapEnv: 'http://schemas.xmlsoap.org/soap/envelope/',
|
|
Xsd: 'http://www.w3.org/2001/XMLSchema',
|
|
Xsi: 'http://www.w3.org/2001/XMLSchema-instance',
|
|
Cwmp: 'urn:dslforum-org:cwmp-1-4',
|
|
},
|
|
}
|
|
|
|
export class SoapEnvelopeAttribute {
|
|
public SoapEnc: string
|
|
public SoapEnv: string
|
|
public Xsd: string
|
|
public Xsi: string
|
|
public Cwmp: string
|
|
|
|
constructor(props: NamespaceDescriptor | Record<string, string> = NAMESPACES['1.0']) {
|
|
this.SoapEnc = props?.SoapEnc || 'http://schemas.xmlsoap.org/soap/encoding/'
|
|
this.SoapEnv = props?.SoapEnv || 'http://schemas.xmlsoap.org/soap/envelope/'
|
|
this.Xsd = props?.Xsd || 'http://www.w3.org/2001/XMLSchema'
|
|
this.Xsi = props?.Xsi || 'http://www.w3.org/2001/XMLSchema-instance'
|
|
this.Cwmp = props?.Cwmp || 'urn:dslforum-org:cwmp-1-0'
|
|
}
|
|
|
|
public isEqualTo(namespace: NamespaceDescriptor): boolean {
|
|
return (
|
|
this.SoapEnc === namespace.SoapEnc &&
|
|
this.SoapEnv === namespace.SoapEnv &&
|
|
this.Xsd === namespace.Xsd &&
|
|
this.Xsi === namespace.Xsi &&
|
|
this.Cwmp === namespace.Cwmp
|
|
)
|
|
}
|
|
}
|
|
|
|
export class SoapCwmpIdAttribute {
|
|
MustUnderstand: string
|
|
|
|
constructor(props: { MustUnderstand?: string } = {}) {
|
|
this.MustUnderstand = props.MustUnderstand || '1'
|
|
}
|
|
|
|
getXml(): string {
|
|
return ` soap-env:mustUnderstand="${this.MustUnderstand}"`
|
|
}
|
|
}
|
|
|
|
export class CwmpID {
|
|
$?: SoapCwmpIdAttribute
|
|
_?: string
|
|
|
|
constructor(props: { $?: { MustUnderstand?: string }; _?: string } = {}) {
|
|
this.$ = props?.$ ? new SoapCwmpIdAttribute(props.$) : undefined
|
|
this._ = props._ || ''
|
|
}
|
|
|
|
getXml(): string {
|
|
return `<cwmp:ID${this.$?.getXml() || ''}>${this._}</cwmp:ID>`
|
|
}
|
|
}
|
|
|
|
export type CwmpBody = Cwmp_1_0 | Cwmp_1_1 | Cwmp_1_2 | Cwmp_1_3 | Cwmp_1_4
|
|
|
|
export class SoapEnvelopeHeader {
|
|
ID: CwmpID
|
|
NoMoreRequests: number
|
|
SessionTimeout?: SessionTimeout
|
|
SupportedCWMPVersions?: SupportedCWMPVersions
|
|
UseCWMPVersion?: UseCWMPVersion
|
|
|
|
constructor(props: Record<string, unknown> = {}) {
|
|
this.ID = new CwmpID(props?.ID as any)
|
|
this.NoMoreRequests = (props?.NoMoreRequests as number) || 0
|
|
this.SessionTimeout = props?.SessionTimeout ? new SessionTimeout(props.SessionTimeout) : undefined
|
|
this.SupportedCWMPVersions = props?.SupportedCWMPVersions
|
|
? new SupportedCWMPVersions(props.SupportedCWMPVersions)
|
|
: undefined
|
|
this.UseCWMPVersion = props?.UseCWMPVersion ? new UseCWMPVersion(props.UseCWMPVersion) : undefined
|
|
}
|
|
}
|
|
|
|
export class SoapEnvelope {
|
|
$?: SoapEnvelopeAttribute
|
|
Header: SoapEnvelopeHeader
|
|
Body: CwmpBody
|
|
version: '1.0' | '1.1' | '1.2' | '1.3' | '1.4'
|
|
|
|
constructor(props: Record<string, unknown> = {}) {
|
|
this.version = (props?.version as '1.0' | '1.1' | '1.2' | '1.3' | '1.4') || '1.0'
|
|
this.$ = props?.$ ? new SoapEnvelopeAttribute(props.$ as any) : new SoapEnvelopeAttribute(NAMESPACES[this.version])
|
|
this.Header = new SoapEnvelopeHeader((props.Header as Record<string, unknown>) || {})
|
|
|
|
const bodyProps = (props.Body as Record<string, unknown>) || {}
|
|
switch (this.version) {
|
|
case '1.4': this.Body = new Cwmp_1_4(bodyProps); break
|
|
case '1.3': this.Body = new Cwmp_1_3(bodyProps); break
|
|
case '1.2': this.Body = new Cwmp_1_2(bodyProps); break
|
|
case '1.1': this.Body = new Cwmp_1_1(bodyProps); break
|
|
default: this.Body = new Cwmp_1_0(bodyProps); break
|
|
}
|
|
}
|
|
|
|
getXml(): string {
|
|
const headerParts: string[] = []
|
|
if (this.Header.ID) headerParts.push(this.Header.ID.getXml())
|
|
if (this.Header.SessionTimeout) {
|
|
headerParts.push(
|
|
`<cwmp:SessionTimeout soap-env:mustUnderstand="${this.Header.SessionTimeout.MustUnderstand}">${this.Header.SessionTimeout._}</cwmp:SessionTimeout>`
|
|
)
|
|
}
|
|
if (this.Header.SupportedCWMPVersions) {
|
|
headerParts.push(
|
|
`<cwmp:SupportedCWMPVersions${this.Header.SupportedCWMPVersions.MustUnderstand !== undefined ? ` soap-env:mustUnderstand="${this.Header.SupportedCWMPVersions.MustUnderstand}"` : ''}>${this.Header.SupportedCWMPVersions._}</cwmp:SupportedCWMPVersions>`
|
|
)
|
|
}
|
|
if (this.Header.UseCWMPVersion) {
|
|
headerParts.push(
|
|
`<cwmp:UseCWMPVersion soap-env:mustUnderstand="${this.Header.UseCWMPVersion.MustUnderstand}">${this.Header.UseCWMPVersion._}</cwmp:UseCWMPVersion>`
|
|
)
|
|
}
|
|
// noMoreRequests est un header CPE→ACS uniquement (TR-069 §3.7.1.4) — ne pas l'émettre côté ACS
|
|
|
|
return `<soap-env:Envelope
|
|
xmlns:soap-enc="${this.$?.SoapEnc}"
|
|
xmlns:soap-env="${this.$?.SoapEnv}"
|
|
xmlns:xsd="${this.$?.Xsd}"
|
|
xmlns:xsi="${this.$?.Xsi}"
|
|
xmlns:cwmp="${this.$?.Cwmp}">
|
|
<soap-env:Header>
|
|
${headerParts.join('\n ')}
|
|
</soap-env:Header>
|
|
<soap-env:Body>
|
|
${
|
|
this.Body.InformResponse?.getXml() ||
|
|
this.Body.GetParameterValues?.getXml() ||
|
|
this.Body.GetParameterNames?.getXml() ||
|
|
this.Body.GetParameterAttributes?.getXml() ||
|
|
this.Body.SetParameterValues?.getXml() ||
|
|
this.Body.SetParameterAttributes?.getXml() ||
|
|
this.Body.ScheduleInform?.getXml() ||
|
|
this.Body.Download?.getXml() ||
|
|
this.Body.Upload?.getXml() ||
|
|
this.Body.Reboot?.getXml() ||
|
|
this.Body.FactoryReset?.getXml() ||
|
|
this.Body.TransferCompleteResponse?.getXml() ||
|
|
''
|
|
}
|
|
</soap-env:Body>
|
|
</soap-env:Envelope>`
|
|
}
|
|
}
|