You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2019/01/23 16:13:42 UTC
[incubator-plc4x] branch develop updated: - Added a merged dfdl
schema joining TPKT,
COTP and S7 schema.develop - Started creating a testsuite for this merged
schema.
This is an automated email from the ASF dual-hosted git repository.
cdutz pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git
The following commit(s) were added to refs/heads/develop by this push:
new d3d2cde - Added a merged dfdl schema joining TPKT, COTP and S7 schema.develop - Started creating a testsuite for this merged schema.
d3d2cde is described below
commit d3d2cde21cc1726cbae16ace2452f5d63d9c7d0d
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Wed Jan 23 17:13:37 2019 +0100
- Added a merged dfdl schema joining TPKT, COTP and S7 schema.develop
- Started creating a testsuite for this merged schema.
---
.../src/main/dfdl/daffodil-built-in-catalog.xml | 4 +-
.../apache/plc4x/protocols/cotp-protocol.dfdl.xsd | 8 +-
.../protocols/s7-full-stack-protocol.dfdl.xsd | 863 +++++++++++++++++++++
protocols/src/main/java/.keepMe | 4 +
.../plc4x/protocols/S7FullStackProtocolTest.java | 31 +
.../plc4x/protocols/s7-full-stack-protocol.tdml | 704 +++++++++++++++++
6 files changed, 1609 insertions(+), 5 deletions(-)
diff --git a/protocols/src/main/dfdl/daffodil-built-in-catalog.xml b/protocols/src/main/dfdl/daffodil-built-in-catalog.xml
index db26ac7..ae2a712 100644
--- a/protocols/src/main/dfdl/daffodil-built-in-catalog.xml
+++ b/protocols/src/main/dfdl/daffodil-built-in-catalog.xml
@@ -20,6 +20,8 @@
uri="org/apache/plc4x/protocols/tpkt-protocol.dfdl.xsd"/>
<uri name="http://plc4x.apache.org/cotp"
uri="org/apache/plc4x/protocols/cotp-protocol.dfdl.xsd"/>
- <uri name="http://plc4x.apache.org/cotp"
+ <uri name="http://plc4x.apache.org/s7"
uri="org/apache/plc4x/protocols/s7-protocol.dfdl.xsd"/>
+ <uri name="http://plc4x.apache.org/s7-full"
+ uri="org/apache/plc4x/protocols/s7-full-stack-protocol.dfdl.xsd"/>
</catalog>
\ No newline at end of file
diff --git a/protocols/src/main/dfdl/org/apache/plc4x/protocols/cotp-protocol.dfdl.xsd b/protocols/src/main/dfdl/org/apache/plc4x/protocols/cotp-protocol.dfdl.xsd
index 14cbfb3..665c4b1 100644
--- a/protocols/src/main/dfdl/org/apache/plc4x/protocols/cotp-protocol.dfdl.xsd
+++ b/protocols/src/main/dfdl/org/apache/plc4x/protocols/cotp-protocol.dfdl.xsd
@@ -57,7 +57,7 @@
<xs:restriction base="xs:unsignedShort"/>
</xs:simpleType>
- <xs:simpleType name="tpduType">
+ <xs:simpleType name="CotpTpduType">
<xs:restriction base="xs:unsignedByte">
<xs:enumeration id="tpduTypeConnectionRequest" value="224">
<xs:annotation>
@@ -92,7 +92,7 @@
</xs:restriction>
</xs:simpleType>
- <xs:simpleType name="parameterType">
+ <xs:simpleType name="CotpParameterType">
<xs:restriction base="xs:unsignedByte">
<xs:enumeration value="192">
<xs:annotation>
@@ -134,7 +134,7 @@
<xs:sequence>
<!-- Length of the COTP header data -->
<xs:element name="headerLength" type="cotp:byte"/>
- <xs:element name="type" type="cotp:tpduType"/>
+ <xs:element name="type" type="cotp:CotpTpduType"/>
<xs:choice dfdl:choiceDispatchKey="{type}">
<xs:element dfdl:choiceBranchKey="224" ref="cotp:CotpTpduConnectionRequest"/>
<xs:element dfdl:choiceBranchKey="208" ref="cotp:CotpTpduConnectionResponse"/>
@@ -229,7 +229,7 @@
<xs:element name="parameter" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
- <xs:element name="type" type="cotp:parameterType"/>
+ <xs:element name="type" type="cotp:CotpParameterType"/>
<xs:element name="parameterLength" type="cotp:byte"/>
<xs:choice dfdl:choiceDispatchKey="{type}">
<xs:element dfdl:choiceBranchKey="192" ref="cotp:CotpParameterTpduSize"/>
diff --git a/protocols/src/main/dfdl/org/apache/plc4x/protocols/s7-full-stack-protocol.dfdl.xsd b/protocols/src/main/dfdl/org/apache/plc4x/protocols/s7-full-stack-protocol.dfdl.xsd
new file mode 100644
index 0000000..f220055
--- /dev/null
+++ b/protocols/src/main/dfdl/org/apache/plc4x/protocols/s7-full-stack-protocol.dfdl.xsd
@@ -0,0 +1,863 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ -->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+ xmlns:s7f="http://plc4x.apache.org/s7-full"
+ xmlns:fn="http://www.w3.org/2005/xpath-functions"
+ targetNamespace="http://plc4x.apache.org/s7-full">
+
+ <xs:annotation>
+ <xs:appinfo source="http://www.ogf.org/dfdl/">
+ <dfdl:defineVariable name="messageType" type="xs:string"/>
+ <dfdl:defineFormat name="s7FullFormat">
+ <dfdl:format representation="binary"
+ binaryNumberRep="binary"
+ byteOrder="bigEndian"
+ lengthKind="implicit" lengthUnits="bytes" length="0"
+ occursCountKind="implicit"
+ textOutputMinLength="0"
+ alignment="1" alignmentUnits="bits"
+ leadingSkip="0" trailingSkip="0"
+ textPadKind="none" ignoreCase="no"
+ encoding="utf-8" truncateSpecifiedLengthString="no"
+ initiator="" terminator=""
+ sequenceKind="ordered" separator=""
+ escapeSchemeRef="" initiatedContent="no"/>
+ </dfdl:defineFormat>
+ <dfdl:format ref="s7f:s7FullFormat"/>
+ </xs:appinfo>
+ </xs:annotation>
+
+ <!--
+
+ Simple type definition.
+
+ -->
+
+ <xs:simpleType name="bit" dfdl:lengthUnits="bits" dfdl:length="1" dfdl:lengthKind="explicit">
+ <xs:restriction base="xs:boolean"/>
+ </xs:simpleType>
+
+ <xs:simpleType name="byte" dfdl:lengthUnits="bytes" dfdl:length="1" dfdl:lengthKind="explicit">
+ <xs:restriction base="xs:unsignedByte"/>
+ </xs:simpleType>
+
+ <xs:simpleType name="short" dfdl:lengthUnits="bytes" dfdl:length="2" dfdl:lengthKind="explicit">
+ <xs:restriction base="xs:unsignedShort"/>
+ </xs:simpleType>
+
+ <xs:simpleType name="hexByte" dfdl:lengthUnits="bytes" dfdl:length="1" dfdl:lengthKind="explicit">
+ <xs:restriction base="xs:hexBinary"/>
+ </xs:simpleType>
+
+ <!--
+
+ TPKT - Iso-On-TCP
+
+ -->
+
+ <xs:element name="TpktMessage" type="s7f:TpktMessageType"/>
+
+ <xs:complexType name="TpktMessageType">
+ <xs:sequence>
+ <!-- TPKT Magic Byte always 0x03 -->
+ <xs:element name="magicByte" type="s7f:byte">
+ <xs:annotation>
+ <xs:appinfo source="http://www.ogf.org/dfdl/">
+ <dfdl:assert message="Magic number was not 0x03."
+ test="{. eq 3}"/>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="reserved" type="s7f:byte"/>
+ <xs:element name="length" type="s7f:short"/>
+ <xs:element name="userData" type="s7f:CotpMessageType"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <!--
+
+ ISO 8073/X.224 - ISO-TP - COTP - Connection-Oriented Transport Protocol Messages
+
+ -->
+
+ <xs:simpleType name="CotpTpduType">
+ <xs:restriction base="xs:unsignedByte">
+ <xs:enumeration id="tpduTypeConnectionRequest" value="224">
+ <xs:annotation>
+ <xs:appinfo source="http://plc4x.apache.org/">ConnectionRequest</xs:appinfo>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration id="tpduTypeConnectionResponse" value="208">
+ <xs:annotation>
+ <xs:appinfo source="http://plc4x.apache.org/">ConnectionResponse</xs:appinfo>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="128">
+ <xs:annotation>
+ <xs:appinfo source="http://plc4x.apache.org/">DisconnectRequest</xs:appinfo>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="192">
+ <xs:annotation>
+ <xs:appinfo source="http://plc4x.apache.org/">DisconnectResponse</xs:appinfo>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="112">
+ <xs:annotation>
+ <xs:appinfo source="http://plc4x.apache.org/">Error</xs:appinfo>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="240">
+ <xs:annotation>
+ <xs:appinfo source="http://plc4x.apache.org/">Data</xs:appinfo>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="CotpParameterType">
+ <xs:restriction base="xs:unsignedByte">
+ <xs:enumeration value="192">
+ <xs:annotation>
+ <xs:appinfo source="http://plc4x.apache.org/">TpduSize</xs:appinfo>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="193">
+ <xs:annotation>
+ <xs:appinfo source="http://plc4x.apache.org/">CallingTsap</xs:appinfo>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="194">
+ <xs:annotation>
+ <xs:appinfo source="http://plc4x.apache.org/">CalledTsap</xs:appinfo>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="195">
+ <xs:annotation>
+ <xs:appinfo source="http://plc4x.apache.org/">Checksum</xs:appinfo>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="224">
+ <xs:annotation>
+ <xs:appinfo source="http://plc4x.apache.org/">DisconnectAdditionalInformation</xs:appinfo>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="CotpMessageType">
+ <xs:sequence>
+ <!-- Length of the COTP header data -->
+ <xs:element name="headerLength" type="s7f:byte"/>
+ <xs:element name="type" type="s7f:CotpTpduType"/>
+ <xs:choice dfdl:choiceDispatchKey="{type}">
+ <xs:element dfdl:choiceBranchKey="224" ref="s7f:CotpTpduConnectionRequest"/>
+ <xs:element dfdl:choiceBranchKey="208" ref="s7f:CotpTpduConnectionResponse"/>
+ <xs:element dfdl:choiceBranchKey="128" ref="s7f:CotpTpduDisconnectRequest"/>
+ <xs:element dfdl:choiceBranchKey="192" ref="s7f:CotpTpduDisconnectResponse"/>
+ <xs:element dfdl:choiceBranchKey="112" ref="s7f:CotpTpduError"/>
+ <xs:element dfdl:choiceBranchKey="240" ref="s7f:CotpTpduData"/>
+ </xs:choice>
+ <xs:element name="userData" type="s7f:S7MessageType" minOccurs="0"
+ dfdl:occursCountKind="expression" dfdl:occursCount="{if((../../length - (../headerLength + 1)) gt 0) then 1 else 0}"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:element name="CotpTpduConnectionRequest">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="destinationReference" type="s7f:short"/>
+ <xs:element name="sourceReference" type="s7f:short"/>
+ <xs:element name="protocolClass" type="s7f:byte"/>
+ <xs:element ref="s7f:parameters" minOccurs="0"
+ dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes" dfdl:length="{../../headerLength - 6}"
+ dfdl:occursCountKind="expression"
+ dfdl:occursCount="{if(../../headerLength gt 6) then 1 else 0}"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="CotpTpduConnectionResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="destinationReference" type="s7f:short"/>
+ <xs:element name="sourceReference" type="s7f:short"/>
+ <xs:element name="protocolClass" type="s7f:byte"/>
+ <xs:element ref="s7f:parameters" minOccurs="0"
+ dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes" dfdl:length="{../../headerLength - 6}"
+ dfdl:occursCountKind="expression"
+ dfdl:occursCount="{if(../../headerLength gt 6) then 1 else 0}"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="CotpTpduDisconnectRequest">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="destinationReference" type="s7f:short"/>
+ <xs:element name="sourceReference" type="s7f:short"/>
+ <xs:element name="disconnectReason" type="s7f:byte"/>
+ <xs:element ref="s7f:parameters" minOccurs="0"
+ dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes" dfdl:length="{../../headerLength - 6}"
+ dfdl:occursCountKind="expression"
+ dfdl:occursCount="{if(../../headerLength gt 6) then 1 else 0}"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="CotpTpduDisconnectResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="destinationReference" type="s7f:short"/>
+ <xs:element name="sourceReference" type="s7f:short"/>
+ <xs:element ref="s7f:parameters" minOccurs="0"
+ dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes" dfdl:length="{../../headerLength - 5}"
+ dfdl:occursCountKind="expression"
+ dfdl:occursCount="{if(../../headerLength gt 5) then 1 else 0}"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="CotpTpduError">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="destinationReference" type="s7f:short"/>
+ <xs:element name="rejectCause" type="s7f:byte"/>
+ <xs:element ref="s7f:parameters" minOccurs="0"
+ dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes" dfdl:length="{../../headerLength - 4}"
+ dfdl:occursCountKind="expression"
+ dfdl:occursCount="{if(../../headerLength gt 4) then 1 else 0}"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="CotpTpduData">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="endOfTransmission" type="xs:unsignedInt"
+ dfdl:lengthKind="explicit" dfdl:lengthUnits="bits" dfdl:length="1"/>
+ <xs:element name="tpduRef" type="xs:unsignedInt"
+ dfdl:lengthKind="explicit" dfdl:lengthUnits="bits" dfdl:length="7"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="parameters">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="parameter" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="type" type="s7f:CotpParameterType"/>
+ <xs:element name="parameterLength" type="s7f:byte"/>
+ <xs:choice dfdl:choiceDispatchKey="{type}">
+ <xs:element dfdl:choiceBranchKey="192" ref="s7f:CotpParameterTpduSize"/>
+ <xs:element dfdl:choiceBranchKey="193" ref="s7f:CotpParameterCallingTsap"/>
+ <xs:element dfdl:choiceBranchKey="194" ref="s7f:CotpParameterCalledTsap"/>
+ <xs:element dfdl:choiceBranchKey="195" ref="s7f:CotpParameterChecksum"/>
+ <xs:element dfdl:choiceBranchKey="224"
+ ref="s7f:CotpParameterDisconnectAdditionalInformation"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="CotpParameterTpduSize">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="tpduSize" type="s7f:byte"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="CotpParameterCallingTsap">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="tsapId" type="s7f:short"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="CotpParameterCalledTsap">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="tsapId" type="s7f:short"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="CotpParameterChecksum">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="checksum" type="s7f:byte"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="CotpParameterDisconnectAdditionalInformation">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="data" type="xs:hexBinary"
+ dfdl:byteOrder="bigEndian" dfdl:lengthUnits="bytes" dfdl:lengthKind="explicit"
+ dfdl:length="{../../parameterLength}"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <!--
+
+ S7 Types
+
+ -->
+
+ <xs:complexType name="S7MessageType">
+ <xs:sequence>
+ <!-- S7 Magic Byte always 0x32 -->
+ <xs:element name="magicByte" type="s7f:byte">
+ <xs:annotation>
+ <xs:appinfo source="http://www.ogf.org/dfdl/">
+ <dfdl:assert message="Magic number was not 0x32."
+ test="{. eq 50}"/>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="type" type="s7f:byte"/>
+ <!--
+ Unfortunately the response for a CPU Functions request follows the rules of a
+ response, however has the header structure of a request
+ (no error code or error class). As mapping to the same type is not allowed,
+ we map to strings and use that as choice-key.
+ -->
+ <xs:choice dfdl:choiceDispatchKey="{
+ if(type eq 1) then 'request'
+ else if(type eq 3) then 'response'
+ else if(type eq 7) then 'response'
+ else 'unknown'
+ }">
+ <xs:element dfdl:choiceBranchKey="request" ref="s7f:S7RequestMessage"/>
+ <xs:element dfdl:choiceBranchKey="response" ref="s7f:S7ResponseMessage"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:element name="S7RequestMessage">
+ <xs:complexType>
+ <xs:sequence>
+ <!-- Reserved value always 0x0000 -->
+ <xs:element name="reserved" type="s7f:short" fixed="0"/>
+ <xs:element name="tpduReference" type="s7f:short"/>
+ <xs:element name="parametersLength" type="s7f:short"/>
+ <xs:element name="payloadsLength" type="s7f:short"/>
+ <xs:element name="parameters" minOccurs="0"
+ dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes" dfdl:length="{../parametersLength}"
+ dfdl:occursCountKind="expression"
+ dfdl:occursCount="{if(../parametersLength gt 0) then 1 else 0}">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="parameter" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="type" type="s7f:byte"/>
+ <xs:choice dfdl:choiceDispatchKey="{type}">
+ <xs:element dfdl:choiceBranchKey="240"
+ ref="s7f:S7GeneralParameterSetupCommunication"/>
+ <xs:element dfdl:choiceBranchKey="0"
+ ref="s7f:SS7RequestParameterCPUService"/>
+ <xs:element dfdl:choiceBranchKey="4" ref="s7f:S7RequestParameterReadVar"/>
+ <xs:element dfdl:choiceBranchKey="5" ref="s7f:S7RequestParameterWriteVar"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <!--
+ As we might be outputting an empty payload block for a parameter that might not have a payload,
+ we have to output this element if the parameters are not empty. The case that the payloads are
+ not empty but the parameters are can't happen during normal operation.
+ -->
+ <xs:element name="payloads" minOccurs="0"
+ dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes" dfdl:length="{../payloadsLength}"
+ dfdl:occursCountKind="expression"
+ dfdl:occursCount="{if(../parametersLength gt 0) then 1 else 0}">
+ <xs:complexType>
+ <xs:sequence>
+ <!--
+ For every parameter we'll be outputting a payload block, even if this might be empty.
+ This is required in order to find the matching parameter for every payload we might
+ be having. We need to match these as otherwise we couldn't determin the type of a
+ payload as this has no type information and we need to be able to access the number
+ of items for a read/write request in order to process the correct number of items in
+ the payload.
+ -->
+ <xs:element name="payload" maxOccurs="unbounded"
+ dfdl:occursCountKind="expression"
+ dfdl:occursCount="{fn:count(../../parameters[1]/parameter)}">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice dfdl:choiceDispatchKey="{../../parameters[1]/parameter[dfdl:occursIndex()]/type}">
+ <xs:element dfdl:choiceBranchKey="240"
+ ref="s7f:S7GeneralPayloadSetupCommunication"/>
+ <xs:element dfdl:choiceBranchKey="0" ref="s7f:S7RequestPayloadCpuServices"/>
+ <xs:element dfdl:choiceBranchKey="4" ref="s7f:S7RequestPayloadReadVar"/>
+ <xs:element dfdl:choiceBranchKey="5" ref="s7f:S7RequestPayloadWriteVar"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="S7ResponseMessage">
+ <xs:complexType>
+ <xs:sequence>
+ <!-- Reserved value always 0x0000 -->
+ <xs:element name="reserved" type="s7f:short" fixed="0"/>
+ <xs:element name="tpduReference" type="s7f:short"/>
+ <xs:element name="parametersLength" type="s7f:short"/>
+ <xs:element name="payloadsLength" type="s7f:short"/>
+ <!-- UserData (type 7) responses don't have the error class and code -->
+ <xs:element name="errorClass" type="s7f:byte" minOccurs="0"
+ dfdl:occursCountKind="expression" dfdl:occursCount="{if(../../type eq 3) then 1 else 0}"/>
+ <xs:element name="errorCode" type="s7f:byte" minOccurs="0"
+ dfdl:occursCountKind="expression" dfdl:occursCount="{if(../../type eq 3) then 1 else 0}"/>
+ <xs:element name="parameters" minOccurs="0"
+ dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes" dfdl:length="{../parametersLength}"
+ dfdl:occursCountKind="expression"
+ dfdl:occursCount="{if(../parametersLength gt 0) then 1 else 0}">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="parameter" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="type" type="s7f:byte"/>
+ <xs:choice dfdl:choiceDispatchKey="{type}">
+ <xs:element dfdl:choiceBranchKey="240"
+ ref="s7f:S7GeneralParameterSetupCommunication"/>
+ <xs:element dfdl:choiceBranchKey="0"
+ ref="s7f:S7ResponseParameterCPUService"/>
+ <xs:element dfdl:choiceBranchKey="4" ref="s7f:S7ResponseParameterReadVar"/>
+ <xs:element dfdl:choiceBranchKey="5" ref="s7f:S7ResponseParameterWriteVar"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <!--
+ As we might be outputting an empty payload block for a parameter that might not have a payload,
+ we have to output this element if the parameters are not empty. The case that the payloads are
+ not empty but the parameters are can't happen during normal operation.
+ -->
+ <xs:element name="payloads" minOccurs="0"
+ dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes" dfdl:length="{../payloadsLength}"
+ dfdl:occursCountKind="expression"
+ dfdl:occursCount="{if(../parametersLength gt 0) then 1 else 0}">
+ <xs:complexType>
+ <xs:sequence>
+ <!--
+ For every parameter we'll be outputting a payload block, even if this might be empty.
+ This is required in order to find the matching parameter for every payload we might
+ be having. We need to match these as otherwise we couldn't determin the type of a
+ payload as this has no type information and we need to be able to access the number
+ of items for a read/write request in order to process the correct number of items in
+ the payload.
+ -->
+ <xs:element name="payload" maxOccurs="unbounded"
+ dfdl:occursCountKind="expression"
+ dfdl:occursCount="{fn:count(../../parameters[1]/parameter)}">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice
+ dfdl:choiceDispatchKey="{../../parameters[1]/parameter[dfdl:occursIndex()]/type}">
+ <xs:element dfdl:choiceBranchKey="240"
+ ref="s7f:S7GeneralPayloadSetupCommunication"/>
+ <xs:element dfdl:choiceBranchKey="0" ref="s7f:S7ResponsePayloadCpuServices"/>
+ <xs:element dfdl:choiceBranchKey="4" ref="s7f:S7ResponsePayloadReadVar"/>
+ <xs:element dfdl:choiceBranchKey="5" ref="s7f:S7ResponsePayloadWriteVar"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <!--
+
+ Parameters.
+
+ -->
+
+ <xs:element name="S7GeneralParameterSetupCommunication">
+ <xs:complexType>
+ <xs:sequence>
+ <!-- Reserved value always 0x00 -->
+ <xs:element name="reserved" type="s7f:byte" fixed="0"/>
+ <xs:element name="maxAmqCaller" type="s7f:short"/>
+ <xs:element name="maxAmqCallee" type="s7f:short"/>
+ <xs:element name="pduLength" type="s7f:short"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="SS7RequestParameterCPUService">
+ <xs:complexType>
+ <xs:sequence>
+ <!-- Fixed header 0x0112 274 -> -->
+ <xs:element name="header" type="s7f:short"/><!-- fixed="274"-->
+ <xs:element name="length" type="s7f:byte"/><!-- fixed="4"-->
+ <!-- Request: 0x11 -> 17 -->
+ <xs:element name="typeCode" type="s7f:byte"/><!-- fixed="17"-->
+ <!-- First 4 bits: Request 0x40, last 4 bits: Function Group 0x04 = 0x44 -> 68 -->
+ <xs:element name="functionGroup" type="s7f:byte"/><!-- fixed="68"-->
+ <!-- READ SSL = 0x01 -->
+ <xs:element name="subFunctionGroup" type="s7f:byte"/><!-- fixed="1"-->
+ <xs:element name="sequenceNumber" type="s7f:byte"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="S7ResponseParameterCPUService">
+ <xs:complexType>
+ <xs:sequence>
+ <!-- Fixed header 0x0112 274 -> -->
+ <xs:element name="header" type="s7f:short"/><!-- fixed="274"-->
+ <xs:element name="paramLength" type="s7f:byte"/><!-- fixed="8"-->
+ <!-- Response: 0x12 -> 18 -->
+ <xs:element name="typeCode" type="s7f:byte"/><!-- fixed="18"-->
+ <!-- First 4 bits: Response 0x80, last 4 bits: Function Group 0x04 = 0x84 -> 132 -->
+ <xs:element name="functionGroup" type="s7f:byte"/><!-- fixed="132"-->
+ <!-- READ SSL = 0x01 -->
+ <xs:element name="subFunctionGroup" type="s7f:byte"/><!-- fixed="1"-->
+ <xs:element name="sequenceNumber" type="s7f:byte"/>
+ <xs:element name="dataUnitReferenceNumber" type="s7f:byte"/>
+ <xs:element name="lastDataUnit" type="s7f:byte"/>
+ <xs:element name="error" type="s7f:short"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="S7RequestParameterReadVar">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="numItems" type="s7f:byte"/>
+ <xs:element name="items" minOccurs="0"
+ dfdl:occursCountKind="expression" dfdl:occursCount="{if(../numItems gt 0) then 1 else 0}">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="item" minOccurs="0"
+ dfdl:occursCountKind="expression" dfdl:occursCount="{../../numItems}">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="type" type="s7f:byte"/>
+ <xs:choice dfdl:choiceDispatchKey="{type}">
+ <xs:element dfdl:choiceBranchKey="18"
+ ref="s7f:S7RequestParameterReadVarAnyItem"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="S7RequestParameterReadVarAnyItem">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="paramLength" type="s7f:byte"/><!-- fixed="10"-->
+ <!-- Addressing Mode: Any 0x10 -> 16 -->
+ <xs:element name="addressingMode" type="s7f:byte"/><!-- fixed="16"-->
+ <xs:element name="dataType" type="s7f:byte"/>
+ <xs:element name="numElements" type="s7f:short"/>
+ <xs:element name="dataBlockNumber" type="s7f:short"/>
+ <xs:element name="memoryArea" type="s7f:byte"/>
+ <!--
+ The next 3 bytes (24 bits) contain the byte- and bit-offset,
+ were the last byte contains the bit-offset in the last 3 bits
+ and the byteOffset is encoded in the higher level 21 bits
+ -->
+ <xs:element name="byteOffset" type="xs:unsignedInt"
+ dfdl:lengthKind="explicit" dfdl:lengthUnits="bits" dfdl:length="21"/>
+ <xs:element name="bitOffset" type="xs:unsignedInt"
+ dfdl:lengthKind="explicit" dfdl:lengthUnits="bits" dfdl:length="3"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="S7ResponseParameterReadVar">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="numItems" type="s7f:byte"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="S7RequestParameterWriteVar">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="numItems" type="s7f:byte"/>
+ <xs:element name="items" minOccurs="0"
+ dfdl:occursCountKind="expression" dfdl:occursCount="{if(../numItems gt 0) then 1 else 0}">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="item" minOccurs="0"
+ dfdl:occursCountKind="expression" dfdl:occursCount="{../../numItems}">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="type" type="s7f:byte"/>
+ <xs:choice dfdl:choiceDispatchKey="{type}">
+ <xs:element dfdl:choiceBranchKey="18"
+ ref="s7f:S7RequestParameterWriteVarAnyItem"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="S7RequestParameterWriteVarAnyItem">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="itemLength" type="s7f:byte"/><!-- fixed="10"-->
+ <!-- Addressing Mode: Any 0x10 -> 16 -->
+ <xs:element name="addressingMode" type="s7f:byte"/><!-- fixed="16"-->
+ <xs:element name="dataType" type="s7f:byte"/>
+ <xs:element name="numElements" type="s7f:short"/>
+ <xs:element name="dataBlockNumber" type="s7f:short"/>
+ <xs:element name="memoryArea" type="s7f:byte"/>
+ <!--
+ The next 3 bytes (24 bits) contain the byte- and bit-offset,
+ were the last byte contains the bit-offset in the last 3 bits
+ and the byteOffset is encoded in the higher level 21 bits
+ -->
+ <xs:element name="byteOffset" type="xs:unsignedInt"
+ dfdl:lengthKind="explicit" dfdl:lengthUnits="bits" dfdl:length="21"/>
+ <xs:element name="bitOffset" type="xs:unsignedInt"
+ dfdl:lengthKind="explicit" dfdl:lengthUnits="bits" dfdl:length="3"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="S7ResponseParameterWriteVar">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="numItems" type="s7f:byte"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <!--
+
+ Payloads.
+
+ -->
+
+ <xs:element name="S7GeneralPayloadSetupCommunication" type="xs:byte" dfdl:lengthKind="explicit" dfdl:length="0"/>
+
+ <xs:element name="S7RequestPayloadCpuServices">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="transportSize" type="s7f:byte"/><!-- fixed="9"-->
+ <xs:element name="length" type="s7f:byte"/>
+ <xs:element name="sslId" type="s7f:short"/>
+ <xs:element name="sslIndex" type="s7f:short"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="S7ResponsePayloadCpuServices">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="returnCode" type="s7f:byte"/>
+ <!-- Transport Size: Octet String = 0x09 -> 9 -->
+ <xs:element name="transportSize" type="s7f:byte"/><!-- fixed="9"-->
+ <xs:element name="length" type="s7f:short"/>
+ <xs:element name="sslId" type="s7f:short"/>
+ <xs:element name="sslIndex" type="s7f:short"/>
+ <xs:element name="partialList" minOccurs="0"
+ dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes" dfdl:length="{../length - 4}"
+ dfdl:occursCountKind="expression" dfdl:occursCount="{../length gt 4}">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="partialListLengthInWords" type="s7f:short"/>
+ <xs:element name="partialListCount" type="s7f:short"/>
+ <xs:element name="sslDataRecords">
+ <xs:complexType>
+ <xs:sequence dfdl:lengthKind="explicit" dfdl:lengthUnits="bytes"
+ dfdl:length="{../length - 8}">
+ <xs:choice>
+ <xs:element
+ ref="s7f:S7ResponsePayloadCpuServicesSslDataRecordModuleIdentification"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="S7ResponsePayloadCpuServicesSslDataRecordModuleIdentification">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="index" type="s7f:short"/>
+ <xs:element name="articleNumber" type="xs:unsignedByte"
+ dfdl:lengthUnits="bytes" dfdl:length="20" dfdl:lengthKind="explicit"/>
+ <xs:element name="bgType" type="s7f:short"/>
+ <xs:element name="moduleOrOsVersion" type="s7f:short"/>
+ <xs:element name="pgDescriptionFileVersion" type="s7f:short"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="S7RequestPayloadReadVar" type="xs:byte" dfdl:lengthKind="explicit" dfdl:length="0"/>
+
+ <xs:element name="S7ResponsePayloadReadVar">
+ <xs:complexType>
+ <xs:sequence>
+ <!-- The number of items which should be read is transmitted in the matching parameter -->
+ <xs:element name="numItems" type="s7f:byte"
+ dfdl:inputValueCalc="{
+ ../../../../parameters[1]/parameter[dfdl:occursIndex()]/s7f:S7ResponseParameterReadVar/numItems
+ }"/>
+ <xs:element name="item" minOccurs="0"
+ dfdl:occursCountKind="expression" dfdl:occursCount="{../numItems}">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="returnCode" type="s7f:byte"/>
+ <xs:element name="transportSize" type="s7f:byte"/>
+ <xs:element name="rawLength" type="s7f:short"/>
+ <!--
+ For some reason the types BIT, BYTE_WORD_DWORD and INTEGER are transferred in "bits",
+ the rest is transferred in "bytes"
+ -->
+ <xs:element name="lengthInBytes" type="s7f:short" dfdl:inputValueCalc="{
+ if((../transportSize eq 3) or (../transportSize eq 4) or (../transportSize eq 5))
+ then fn:ceiling(../rawLength div 8)
+ else ../rawLength}"/>
+ <xs:element name="data" type="xs:hexBinary"
+ dfdl:byteOrder="bigEndian" dfdl:lengthUnits="bytes" dfdl:lengthKind="explicit"
+ dfdl:length="{../lengthInBytes}"/>
+ <!--
+ Transport sizes: BIT, BYTE_WORD_DWORD and OCTET_STRING require a blank byte.
+ However only if this is not the last item in the result.
+ -->
+ <xs:element name="reserved" type="s7f:byte" minOccurs="0"
+ dfdl:occursCountKind="expression" dfdl:occursCount="{
+ if(((../transportSize eq 3) or
+ (../transportSize eq 4) or
+ (../transportSize eq 9)) and
+ (dfdl:occursIndex() ne ../../numItems)) then 1 else 0}"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="S7RequestPayloadWriteVar">
+ <xs:complexType>
+ <xs:sequence>
+ <!-- The number of items which should be read is transmitted in the matching parameter -->
+ <xs:element name="numItems" type="s7f:byte"
+ dfdl:inputValueCalc="{
+ ../../../../parameters[1]/parameter[dfdl:occursIndex()]/s7f:S7RequestParameterWriteVar/numItems
+ }"/>
+ <xs:element name="item" minOccurs="0"
+ dfdl:occursCountKind="expression" dfdl:occursCount="{../numItems}">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="returnCode" type="s7f:byte"/>
+ <xs:element name="transportSize" type="s7f:byte"/>
+ <xs:element name="rawLength" type="s7f:short"/>
+ <!--
+ For some reason the types BIT, BYTE_WORD_DWORD and INTEGER are transferred in "bits",
+ the rest is transferred in "bytes"
+ -->
+ <xs:element name="lengthInBytes" type="s7f:short" dfdl:inputValueCalc="{
+ if((../transportSize eq 3) or (../transportSize eq 4) or (../transportSize eq 5))
+ then fn:ceiling(../rawLength div 8)
+ else ../rawLength}"/>
+ <xs:element name="data" type="xs:hexBinary"
+ dfdl:byteOrder="bigEndian" dfdl:lengthUnits="bytes" dfdl:lengthKind="explicit"
+ dfdl:length="{../lengthInBytes}"/>
+ <!--
+ Transport sizes: BIT, BYTE_WORD_DWORD and OCTET_STRING require a blank byte.
+ However only if this is not the last item in the result.
+
+ Actually the S7 device will never process data that contains more
+ than one item in a write request, so this is rather a cosmetic fine-tuning.
+ -->
+ <xs:element name="reserved" type="s7f:byte" minOccurs="0"
+ dfdl:occursCountKind="expression" dfdl:occursCount="{
+ if(((../transportSize eq 3) or
+ (../transportSize eq 4) or
+ (../transportSize eq 9)) and
+ (dfdl:occursIndex() ne ../../numItems)) then 1 else 0}"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="S7ResponsePayloadWriteVar">
+ <xs:complexType>
+ <xs:sequence>
+ <!-- The number of items which should be read is transmitted in the matching parameter -->
+ <xs:element name="numItems" type="s7f:byte"
+ dfdl:inputValueCalc="{
+ ../../../../parameters[1]/parameter[dfdl:occursIndex()]/s7f:S7ResponseParameterWriteVar/numItems
+ }"/>
+ <xs:element name="item" minOccurs="0"
+ dfdl:occursCountKind="expression" dfdl:occursCount="{../numItems}">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="returnCode" type="s7f:byte"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+</xs:schema>
\ No newline at end of file
diff --git a/protocols/src/main/java/.keepMe b/protocols/src/main/java/.keepMe
index cf84b4e..97c6314 100644
--- a/protocols/src/main/java/.keepMe
+++ b/protocols/src/main/java/.keepMe
@@ -14,3 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
+This file is required to force the existence of the src/main/java directory
+which activates the "java-module" maven profile.
+
+PLEASE DO NOT DELETE ... it will break the build.
\ No newline at end of file
diff --git a/protocols/src/test/java/org/apache/plc4x/protocols/S7FullStackProtocolTest.java b/protocols/src/test/java/org/apache/plc4x/protocols/S7FullStackProtocolTest.java
new file mode 100644
index 0000000..ddee1e7
--- /dev/null
+++ b/protocols/src/test/java/org/apache/plc4x/protocols/S7FullStackProtocolTest.java
@@ -0,0 +1,31 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+package org.apache.plc4x.protocols;
+
+/**
+ * Executes all tests for the ISO on TCP / TPKT protocol.
+ */
+public class S7FullStackProtocolTest extends AbstractProtocolTest {
+
+ public S7FullStackProtocolTest() {
+ super("org/apache/plc4x/protocols/s7-full-stack-protocol.tdml");
+ }
+
+}
diff --git a/protocols/src/test/resources/org/apache/plc4x/protocols/s7-full-stack-protocol.tdml b/protocols/src/test/resources/org/apache/plc4x/protocols/s7-full-stack-protocol.tdml
new file mode 100644
index 0000000..752d57c
--- /dev/null
+++ b/protocols/src/test/resources/org/apache/plc4x/protocols/s7-full-stack-protocol.tdml
@@ -0,0 +1,704 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ -->
+
+<testSuite xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+ xmlns:test="plc4x-protocol-test"
+ xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData"
+ xmlns:s7="http://plc4x.apache.org/s7-full"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ suiteName="S7 protocol (Full-Stack KPKT + COTP + S7)"
+ description="Testsuite for the full stack of the S7 protocol"
+ defaultRoundTrip="true">
+
+ <tdml:defineSchema name="s7Schema" elementFormDefault="unqualified">
+ <!-- Import the Schema -->
+ <xs:import namespace="http://plc4x.apache.org/s7-full"
+ schemaLocation="s7-full-stack-protocol.dfdl.xsd"/>
+
+ <!-- Import the format settings -->
+ <dfdl:format ref="s7:s7FullFormat"/>
+
+ <!-- Define the root element name and type -->
+ <xs:element name="tpktMessage" type="s7:TpktMessageType"/>
+ </tdml:defineSchema>
+
+ <!--
+ In this test-case the data should be parsable to a valid result.
+ It's a TPKT package containing a COTP connection-response payload.
+ -->
+ <tdml:parserTestCase name="TPKT: tpktPacketContainingCotpConnectResponse"
+ root="tpktMessage"
+ model="s7Schema"
+ description="Simple TKPT packet which contains a COTP Connection-Response as payload.">
+ <!-- Define the input -->
+ <tdml:document>
+ <tdml:documentPart type="byte">0300001211D00001000200C00109C1020100C2020102</tdml:documentPart>
+ </tdml:document>
+
+ <!-- Define the expected output -->
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <!-- Referencing what we defined as root element in the defineSchema section -->
+ <test:tpktMessage>
+ <magicByte>3</magicByte>
+ <reserved>0</reserved>
+ <length>18</length>
+ <userData>
+ <headerLength>17</headerLength>
+ <type>208</type>
+ <CotpTpduConnectionResponse>
+ <destinationReference>1</destinationReference>
+ <sourceReference>2</sourceReference>
+ <protocolClass>0</protocolClass>
+ <parameters>
+ <parameter>
+ <type>192</type>
+ <parameterLength>1</parameterLength>
+ <CotpParameterTpduSize>
+ <tpduSize>9</tpduSize>
+ </CotpParameterTpduSize>
+ </parameter>
+ <parameter>
+ <type>193</type>
+ <parameterLength>2</parameterLength>
+ <CotpParameterCallingTsap>
+ <tsapId>256</tsapId>
+ </CotpParameterCallingTsap>
+ </parameter>
+ <parameter>
+ <type>194</type>
+ <parameterLength>2</parameterLength>
+ <CotpParameterCalledTsap>
+ <tsapId>258</tsapId>
+ </CotpParameterCalledTsap>
+ </parameter>
+ </parameters>
+ </CotpTpduConnectionResponse>
+ </userData>
+ </test:tpktMessage>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <!--
+ In this test-case the packet doesn't start with the required magic byte 0x03.
+ -->
+ <tdml:parserTestCase name="TPKT: invalidMagicByte"
+ root="tpktMessage"
+ model="s7Schema">
+ <tdml:document>
+ <tdml:documentPart type="byte">0400001611D00001000200C00109C1020100C2020102</tdml:documentPart>
+ </tdml:document>
+
+ <tdml:errors>
+ <tdml:error>Parse Error</tdml:error>
+ </tdml:errors>
+ </tdml:parserTestCase>
+
+ <!--
+ In this test-case the payload of the packet doesn't match the
+ length provided in the packet header (Too short)
+ -->
+ <tdml:parserTestCase name="TPKT: tooShortPayload"
+ root="tpktMessage"
+ model="s7Schema">
+ <tdml:document>
+ <tdml:documentPart type="byte">0300001611D00001000200C00109C102010</tdml:documentPart>
+ </tdml:document>
+
+ <tdml:errors>
+ <tdml:error>Parse Error</tdml:error>
+ </tdml:errors>
+ </tdml:parserTestCase>
+
+ <!--
+ In this test-case the payload of the packet doesn't match the
+ length provided in the packet header (Too long)
+ -->
+ <tdml:parserTestCase name="TPKT: tooLongPayload"
+ root="tpktMessage"
+ model="s7Schema">
+ ยด
+ <tdml:document>
+ <tdml:documentPart type="byte">0300001611D00001000200C00109C1020100C20201021234567890</tdml:documentPart>
+ </tdml:document>
+
+ <tdml:errors>
+ <tdml:error>Parse Error</tdml:error>
+ </tdml:errors>
+ </tdml:parserTestCase>
+
+ <!--
+
+ Tests for the basic TPDU types (no parameters)
+
+ -->
+
+ <tdml:parserTestCase name="COTP: typeConnectionRequest"
+ root="tpktMessage"
+ model="s7Schema"
+ description="Minimal valid COTP Connection Request TPDU">
+ <!-- Define the input -->
+ <tdml:document>
+ <tdml:documentPart type="byte">0300000706E00001000200</tdml:documentPart>
+ </tdml:document>
+
+ <!-- Define the expected output -->
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <test:tpktMessage>
+ <magicByte>3</magicByte>
+ <reserved>0</reserved>
+ <length>7</length>
+ <userData>
+ <headerLength>6</headerLength>
+ <type>224</type>
+ <CotpTpduConnectionRequest>
+ <destinationReference>1</destinationReference>
+ <sourceReference>2</sourceReference>
+ <protocolClass>0</protocolClass>
+ </CotpTpduConnectionRequest>
+ </userData>
+ </test:tpktMessage>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="COTP: typeConnectionResponse"
+ root="tpktMessage"
+ model="s7Schema"
+ description="Minimal valid COTP Connection Response TPDU">
+ <!-- Define the input -->
+ <tdml:document>
+ <tdml:documentPart type="byte">0300000706D00001000200</tdml:documentPart>
+ </tdml:document>
+
+ <!-- Define the expected output -->
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <test:tpktMessage>
+ <magicByte>3</magicByte>
+ <reserved>0</reserved>
+ <length>7</length>
+ <userData>
+ <headerLength>6</headerLength>
+ <type>208</type>
+ <CotpTpduConnectionResponse>
+ <destinationReference>1</destinationReference>
+ <sourceReference>2</sourceReference>
+ <protocolClass>0</protocolClass>
+ </CotpTpduConnectionResponse>
+ </userData>
+ </test:tpktMessage>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="COTP: typeDisconnectionRequest"
+ root="tpktMessage"
+ model="s7Schema"
+ description="Minimal valid COTP Disconnection Request TPDU">
+ <!-- Define the input -->
+ <tdml:document>
+ <tdml:documentPart type="byte">0300000706800001000200</tdml:documentPart>
+ </tdml:document>
+
+ <!-- Define the expected output -->
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <test:tpktMessage>
+ <magicByte>3</magicByte>
+ <reserved>0</reserved>
+ <length>7</length>
+ <userData>
+ <headerLength>6</headerLength>
+ <type>128</type>
+ <CotpTpduDisconnectRequest>
+ <destinationReference>1</destinationReference>
+ <sourceReference>2</sourceReference>
+ <disconnectReason>0</disconnectReason>
+ </CotpTpduDisconnectRequest>
+ </userData>
+ </test:tpktMessage>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="COTP: typeDisconnectionResponse"
+ root="tpktMessage"
+ model="s7Schema"
+ description="Minimal valid COTP Disconnection Response TPDU">
+ <!-- Define the input -->
+ <tdml:document>
+ <tdml:documentPart type="byte">0300000605C000010002</tdml:documentPart>
+ </tdml:document>
+
+ <!-- Define the expected output -->
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <test:tpktMessage>
+ <magicByte>3</magicByte>
+ <reserved>0</reserved>
+ <length>6</length>
+ <userData>
+ <headerLength>5</headerLength>
+ <type>192</type>
+ <CotpTpduDisconnectResponse>
+ <destinationReference>1</destinationReference>
+ <sourceReference>2</sourceReference>
+ </CotpTpduDisconnectResponse>
+ </userData>
+ </test:tpktMessage>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="COTP: typeError"
+ root="tpktMessage"
+ model="s7Schema"
+ description="Minimal valid COTP Error TPDU">
+ <!-- Define the input -->
+ <tdml:document>
+ <tdml:documentPart type="byte">030000050470000102</tdml:documentPart>
+ </tdml:document>
+
+ <!-- Define the expected output -->
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <test:tpktMessage>
+ <magicByte>3</magicByte>
+ <reserved>0</reserved>
+ <length>5</length>
+ <userData>
+ <headerLength>4</headerLength>
+ <type>112</type>
+ <CotpTpduError>
+ <destinationReference>1</destinationReference>
+ <rejectCause>2</rejectCause>
+ </CotpTpduError>
+ </userData>
+ </test:tpktMessage>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="COTP: typeData"
+ root="tpktMessage"
+ model="s7Schema"
+ description="Minimal valid COTP Data TPDU">
+ <!-- Define the input -->
+ <tdml:document>
+ <tdml:documentPart type="byte">0300000302F002</tdml:documentPart>
+ </tdml:document>
+
+ <!-- Define the expected output -->
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <test:tpktMessage>
+ <magicByte>3</magicByte>
+ <reserved>0</reserved>
+ <length>3</length>
+ <userData>
+ <headerLength>2</headerLength>
+ <type>240</type>
+ <CotpTpduData>
+ <endOfTransmission>0</endOfTransmission>
+ <tpduRef>2</tpduRef>
+ </CotpTpduData>
+ </userData>
+ </test:tpktMessage>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="COTP: typeDataEndOfTransmission"
+ root="tpktMessage"
+ model="s7Schema"
+ description="Minimal valid COTP Data (End Of Transmission) TPDU">
+ <!-- Define the input -->
+ <tdml:document>
+ <tdml:documentPart type="byte">0300000302F082</tdml:documentPart>
+ </tdml:document>
+
+ <!-- Define the expected output -->
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <test:tpktMessage>
+ <magicByte>3</magicByte>
+ <reserved>0</reserved>
+ <length>3</length>
+ <userData>
+ <headerLength>2</headerLength>
+ <type>240</type>
+ <CotpTpduData>
+ <endOfTransmission>1</endOfTransmission>
+ <tpduRef>2</tpduRef>
+ </CotpTpduData>
+ </userData>
+ </test:tpktMessage>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <!--
+
+ Tests for the parameter types.
+
+ -->
+
+ <tdml:parserTestCase name="COTP: parameterTpduSize"
+ root="tpktMessage"
+ model="s7Schema"
+ description="parameterTpduSize">
+ <!-- Define the input -->
+ <tdml:document>
+ <tdml:documentPart type="byte">0300000A09E00001000200C00109</tdml:documentPart>
+ </tdml:document>
+
+ <!-- Define the expected output -->
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <test:tpktMessage>
+ <magicByte>3</magicByte>
+ <reserved>0</reserved>
+ <length>10</length>
+ <userData>
+ <headerLength>9</headerLength>
+ <type>224</type>
+ <CotpTpduConnectionRequest>
+ <destinationReference>1</destinationReference>
+ <sourceReference>2</sourceReference>
+ <protocolClass>0</protocolClass>
+ <parameters>
+ <parameter>
+ <type>192</type>
+ <parameterLength>1</parameterLength>
+ <CotpParameterTpduSize>
+ <tpduSize>9</tpduSize>
+ </CotpParameterTpduSize>
+ </parameter>
+ </parameters>
+ </CotpTpduConnectionRequest>
+ </userData>
+ </test:tpktMessage>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="COTP: parameterCallingTsap"
+ root="tpktMessage"
+ model="s7Schema"
+ description="parameterCallingTsap">
+ <!-- Define the input -->
+ <tdml:document>
+ <tdml:documentPart type="byte">0300000B0AE00001000200C1020009</tdml:documentPart>
+ </tdml:document>
+
+ <!-- Define the expected output -->
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <test:tpktMessage>
+ <magicByte>3</magicByte>
+ <reserved>0</reserved>
+ <length>11</length>
+ <userData>
+ <headerLength>10</headerLength>
+ <type>224</type>
+ <CotpTpduConnectionRequest>
+ <destinationReference>1</destinationReference>
+ <sourceReference>2</sourceReference>
+ <protocolClass>0</protocolClass>
+ <parameters>
+ <parameter>
+ <type>193</type>
+ <parameterLength>2</parameterLength>
+ <CotpParameterCallingTsap>
+ <tsapId>9</tsapId>
+ </CotpParameterCallingTsap>
+ </parameter>
+ </parameters>
+ </CotpTpduConnectionRequest>
+ </userData>
+ </test:tpktMessage>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="COTP: parameterCalledTsap"
+ root="tpktMessage"
+ model="s7Schema"
+ description="parameterCalledTsap">
+ <!-- Define the input -->
+ <tdml:document>
+ <tdml:documentPart type="byte">0300000B0AE00001000200C2020009</tdml:documentPart>
+ </tdml:document>
+
+ <!-- Define the expected output -->
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <test:tpktMessage>
+ <magicByte>3</magicByte>
+ <reserved>0</reserved>
+ <length>11</length>
+ <userData>
+ <headerLength>10</headerLength>
+ <type>224</type>
+ <CotpTpduConnectionRequest>
+ <destinationReference>1</destinationReference>
+ <sourceReference>2</sourceReference>
+ <protocolClass>0</protocolClass>
+ <parameters>
+ <parameter>
+ <type>194</type>
+ <parameterLength>2</parameterLength>
+ <CotpParameterCalledTsap>
+ <tsapId>9</tsapId>
+ </CotpParameterCalledTsap>
+ </parameter>
+ </parameters>
+ </CotpTpduConnectionRequest>
+ </userData>
+ </test:tpktMessage>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="COTP: parameterChecksum"
+ root="tpktMessage"
+ model="s7Schema"
+ description="parameterChecksum">
+ <!-- Define the input -->
+ <tdml:document>
+ <tdml:documentPart type="byte">0300000A09E00001000200C30109</tdml:documentPart>
+ </tdml:document>
+
+ <!-- Define the expected output -->
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <test:tpktMessage>
+ <magicByte>3</magicByte>
+ <reserved>0</reserved>
+ <length>10</length>
+ <userData>
+ <headerLength>9</headerLength>
+ <type>224</type>
+ <CotpTpduConnectionRequest>
+ <destinationReference>1</destinationReference>
+ <sourceReference>2</sourceReference>
+ <protocolClass>0</protocolClass>
+ <parameters>
+ <parameter>
+ <type>195</type>
+ <parameterLength>1</parameterLength>
+ <CotpParameterChecksum>
+ <checksum>9</checksum>
+ </CotpParameterChecksum>
+ </parameter>
+ </parameters>
+ </CotpTpduConnectionRequest>
+ </userData>
+ </test:tpktMessage>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="COTP: parameterDisconnectAdditionalInformation"
+ root="tpktMessage"
+ model="s7Schema"
+ description="parameterDisconnectAdditionalInformation">
+ <!-- Define the input -->
+ <tdml:document>
+ <tdml:documentPart type="byte">0300000F0EE00001000200E006010203040506</tdml:documentPart>
+ </tdml:document>
+
+ <!-- Define the expected output -->
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <test:tpktMessage>
+ <magicByte>3</magicByte>
+ <reserved>0</reserved>
+ <length>15</length>
+ <userData>
+ <headerLength>14</headerLength>
+ <type>224</type>
+ <CotpTpduConnectionRequest>
+ <destinationReference>1</destinationReference>
+ <sourceReference>2</sourceReference>
+ <protocolClass>0</protocolClass>
+ <parameters>
+ <parameter>
+ <type>224</type>
+ <parameterLength>6</parameterLength>
+ <CotpParameterDisconnectAdditionalInformation>
+ <data>010203040506</data>
+ </CotpParameterDisconnectAdditionalInformation>
+ </parameter>
+ </parameters>
+ </CotpTpduConnectionRequest>
+ </userData>
+ </test:tpktMessage>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <!--
+
+ Tests for typical packets used in PLC4X
+
+ -->
+
+ <tdml:parserTestCase name="COTP: scenarioConnectionRequest"
+ root="tpktMessage"
+ model="s7Schema"
+ description="COTP Connection request used for initiating an S7 protocol connection.">
+ <!-- Define the input -->
+ <tdml:document>
+ <tdml:documentPart type="byte">0300001211E00001000200C1020100C2020102c0010a</tdml:documentPart>
+ </tdml:document>
+
+ <!-- Define the expected output -->
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <test:tpktMessage>
+ <magicByte>3</magicByte>
+ <reserved>0</reserved>
+ <length>18</length>
+ <userData>
+ <headerLength>17</headerLength>
+ <type>224</type>
+ <CotpTpduConnectionRequest>
+ <destinationReference>1</destinationReference>
+ <sourceReference>2</sourceReference>
+ <protocolClass>0</protocolClass>
+ <parameters>
+ <parameter>
+ <type>193</type>
+ <parameterLength>2</parameterLength>
+ <CotpParameterCallingTsap>
+ <tsapId>256</tsapId>
+ </CotpParameterCallingTsap>
+ </parameter>
+ <parameter>
+ <type>194</type>
+ <parameterLength>2</parameterLength>
+ <CotpParameterCalledTsap>
+ <tsapId>258</tsapId>
+ </CotpParameterCalledTsap>
+ </parameter>
+ <parameter>
+ <type>192</type>
+ <parameterLength>1</parameterLength>
+ <CotpParameterTpduSize>
+ <tpduSize>10</tpduSize>
+ </CotpParameterTpduSize>
+ </parameter>
+ </parameters>
+ </CotpTpduConnectionRequest>
+ </userData>
+ </test:tpktMessage>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="COTP: scenarioConnectionResponse"
+ root="tpktMessage"
+ model="s7Schema"
+ description="Minimal valid COTP Message">
+ <!-- Define the input -->
+ <tdml:document>
+ <tdml:documentPart type="byte">0300001211D00001000200C00109C1020100C2020102</tdml:documentPart>
+ </tdml:document>
+
+ <!-- Define the expected output -->
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <test:tpktMessage>
+ <magicByte>3</magicByte>
+ <reserved>0</reserved>
+ <length>18</length>
+ <userData>
+ <headerLength>17</headerLength>
+ <type>208</type>
+ <CotpTpduConnectionResponse>
+ <destinationReference>1</destinationReference>
+ <sourceReference>2</sourceReference>
+ <protocolClass>0</protocolClass>
+ <parameters>
+ <parameter>
+ <type>192</type>
+ <parameterLength>1</parameterLength>
+ <CotpParameterTpduSize>
+ <tpduSize>9</tpduSize>
+ </CotpParameterTpduSize>
+ </parameter>
+ <parameter>
+ <type>193</type>
+ <parameterLength>2</parameterLength>
+ <CotpParameterCallingTsap>
+ <tsapId>256</tsapId>
+ </CotpParameterCallingTsap>
+ </parameter>
+ <parameter>
+ <type>194</type>
+ <parameterLength>2</parameterLength>
+ <CotpParameterCalledTsap>
+ <tsapId>258</tsapId>
+ </CotpParameterCalledTsap>
+ </parameter>
+ </parameters>
+ </CotpTpduConnectionResponse>
+ </userData>
+ </test:tpktMessage>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <!--tdml:parserTestCase name="COTP: scenarioDataTpdu"
+ root="tpktMessage"
+ model="s7Schema"
+ description="Typical Data TPDU used for transferring S7 packets.">
+ <!- Define the input ->
+ <tdml:document>
+ <tdml:documentPart type="byte">0300001f02f080320100000001000e00000401120a10010001000082000004</tdml:documentPart>
+ </tdml:document>
+
+ <!- Define the expected output ->
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <test:tpktMessage>
+ <magicByte>3</magicByte>
+ <reserved>0</reserved>
+ <length>29</length>
+ <userData>
+ <headerLength>2</headerLength>
+ <type>240</type>
+ <CotpTpduData>
+ <endOfTransmission>1</endOfTransmission>
+ <tpduRef>0</tpduRef>
+ </CotpTpduData>
+ </userData>
+ </test:tpktMessage>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase-->
+
+</testSuite>
+
+