Giter Club home page Giter Club logo

commsdsl's Introduction

Overview

This project is a member of CommsChampion Ecosystem. It provides multiple code generators to produce C++11 binary protocol definition code as well as other satellite components that can be used to (fuzz) test the protocol definition, visualize the message contents, debug the protocol messages exchange, as well as create bindings (glue code) for other high level programming languages.

What's Inside

  • commsdsl2comms - A code generator, that produces C++11 code for binary protocol definition out of CommsDSL schema files. The generated outcome is actually a CMake project that can be used to properly install protocol definition headers as well as relevant cmake configuration files. For details on how to use the tool, please read the commsdsl2comms Manual documentation page. For details on the generated CMake project please read the Generated CMake Project Walkthrough documentation page.
  • commsdsl2test - A code generator that produces C++11 code for fuzz testing of the protocol definition produced by the commsdsl2comms. Details are in the Testing Generated Protocol Code documentation page. Build requires explicit cmake enable option.
  • commsdsl2tools_qt - A code generator, that produces the protocol definition plugin code for CommmsChampion Tools, which can be used to visualize message contents as well as debug / observe exchange of the messages between different systems. Details are in the Visual Protocol Analysis documentation page. Build requires explicit cmake enable option.
  • commsdsl2swig - A code generator that produces SWIG interface file(s) for the protocol definition produced by the commsdsl2comms. It allows generation of the bindings (glue code) to other high level programming languages using external swig utility. Details are in the Other Languages Support documentation page. Build requires explicit cmake enable option.
  • commsdsl2emscripten - A code generator that produces emscripten
    bindings for the protocol definition produced by the commsdsl2comms. It allows compilation of the protocol definition C++ code into WebAssembly as well as generation javascript bindings to it. Details are in the WebAssembly Support documentation page. Build requires explicit cmake enable option.
  • libcommsdsl - A C++ library containing common functionality for parsing of the CommsDSL schema files as well code generation. It can be used to implement independent code generators. NOTE, that at this moment, the library is not documented. Please get in touch in case you need it. I'll let you know when it's going to be ready.

License

The code of this project (libraries and tools it contains) is licensed under Apache v2.0 license.

The generated code has no license, the vendor is free to pick any as long as it's compatible with the license of the relevant CommsChampion Ecosystem project.

Tutorial

The cc_tutorial project contains a tutorial on how to use CommsDSL to define binary communication protocol, commsdsl2comms to generate code, and COMMS Library to customize and integrate the protocol definition with the business logic of the application.

How to Build

Detailed instructions on how to build and install all the components can be found in doc/BUILD.md file.

Other Documentation

Please check the doc folder for the available additional documentation.

Versioning

This project will use Semantic Versioning, where MAJOR number will be equal to the latest DSL version (The first number of CommsDSL version) it supports. The MINOR number will indicate various improvements in the code of this repository, and PATCH number will indicate various bug fixes.

Supported Compilers

This project (the code generator and CommsDSL parsing library) is implemented using C++17 programming language. As the result, the supported compilers are:

  • GCC: >=8
  • Clang: >=7
  • MSVC: >= 2017

The generated projects however contain C++11 valid code and supports a bit earlier versions of the compilers:

  • GCC: >=4.8
  • Clang: >=3.8
  • MSVC: >= 2015

Branching Model

This repository will follow the Successful Git Branching Model.

The master branch will always point to the latest release, the development is performed on develop branch. As the result it is safe to just clone the sources of this repository and use it without any extra manipulations of looking for the latest stable version among the tags and checking it out.

Contact Information

For bug reports, feature requests, or any other question you may open an issue here in github or e-mail me directly to: [email protected]. I usually respond within 24 hours.

commsdsl's People

Contributors

arobenko avatar haititi avatar mathisloge avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

commsdsl's Issues

noexcept error with gcc 9

First off, I have been using commschampion ecosystem for a few months, excellent product, thank you!

With the latest ubuntu release 19.10, gcc has been upgraded to version 9, in my case 9.2.1.
commsdsl now throws this error when building

commsdsl/build/commsdsl/src/lib/src/NamespaceImpl.cpp: In constructor ‘commsdsl::NamespaceImpl::NamespaceImpl(xmlNodePtr, commsdsl::ProtocolImpl&)’:
commsdsl/build/commsdsl/src/lib/src/NamespaceImpl.cpp:72:24: error: noexcept-expression evaluates to ‘false’ because of a call to ‘static constexpr unsigned int commsdsl::Protocol::notYetDeprecated()’ [-Werror=noexcept]
72 | m_protocol(protocol)
| ^

Unexpected max serialisation length

I defined the following list

            <list name="VideoBlocks">
                <element>
                    <data name="VideoBlock" length="64"/>
                </element>
                <countPrefix>
                    <int name="VideoBlockCounter" type="uint8" />
                </countPrefix>
            </list>

I get the following error on compile

`error: static assertion failed: Unexpected max serialisation length
  900 |     static_assert(MsgMaxLen == 16352U, "Unexpected max serialisation length");`

If I remove the length property from the data field it compiles fine but I can't use this as each VideoBlock is a fixed length (64 bytes) and I have fields after the VideoBlocks in my protocol.

Am I specifying my schema incorrectly for this case?

many thanks.

ICD generation

Hi Alex,

I'm currently exploring the possibility to generate latex files for automatic ICD generation.
there shouldn't be much missing for a ICD generation. (just the protocol aspect of a ICD.) But I think that this will be a very useful functionality.

https://github.com/mathisloge/commsdsl

I'm letting you know how it works out. Currently i need to dig a bit around the code to get a better understanding.
(Don't expect me to be that fast. I'm currently writing my master thesis and working beside that)

Just by the way, really good code. I was able to find my way around quickly and generated the first latex document.

ASN.1 Parsing/Serialization

This is an extension suggestion for opening up a new application field with respect to ASN.1 parsing/serializing.

ASN.1 is a serialization notation extensively used within the Telecom industry and by many security protocols defined by the IETF, for instance certificates, TLS and OCSP. Even if ASN.1 is an old and complex format it will stay relevant for many years as it is deeply embedded in major telecom and security infrastructure. It is also well known that many current ASN.1 parser implementations are buggy due to poor ad-hoc implementations but also due to the general complexity of ASN.1 itself. Therefore many security issues arise from faulty parsing of protocols and certificates. A simple search for asn at the CVE database reveals some 2350 issues as of today including issues with OpenSSL and major TLS implementations. The systematic and thorough protocol processing of ASN.1 by the Comms framework would eliminate the majority of the issues and also make writing parsers and serializes for ASN.1 much easier.

The ability to serialize ASN.1 would open up new opportunities for the Comms framework within an area where it would also excel; security. If additionally a simple XSLT transformer is created, the Comms (ASN.1) XML notation could be made to closely resemble that of the original by using ASN.1 XML tags rather than Comms tags.

It turns out that ASN.1 can be supported elegantly by the Comms framework except for a single showstopper; the ASN.1 length field, see ITU-T X.690, section 8.1.3, for a description. Due to this issue Comms ASN.1 XML schemas cannot be designed without adding major complexity, thus rendering the schemas hard understand an use.

As the ASN.1 length field is similar to the varint field already present in Comms it is suggested that an ASN.1 varint field is added to the Comms framework to enable ASN.1 parsing/serializing. As a further improvement, a simple XSLT transformer can be written to allow for writing ASN.1 XML schemas with original ASN.1 type tags rather than Comms type tags. This would enable XML schema writing in an XML notation that closely resembles that of the original ASN.1 notation and thus simplify schema validation.

A more general alternative to the dedicated ASN.1 varint might be a new kind of integer; Calculation int. The calculation int would apply user defined callbacks to determine parameters like length and value from a fields raw data. This way the ASN.1 length field could be modeled without adding ASN.1 specific fields to Comms. It would also be a more generic feature that might be useful elsewhere too and to simplify future extensions. Unfortunately I cannot judge if the solution is feasible given the architecture of the framework.

Given the above suggestions I tried out some possible ASN.1 lookalike schema outlines. RFC 6960 OCSP responder shows one possible syntax for the ASN.1 schema defined in RFC6960 and written in a Comms ASN.1 friendly format. The schema closely resembles the original ASN.1 notation and can be transformed to actual Comms XML with only trivial XSLT post-processing. Equivalence between the original ANS.1 format in RFC 6960 and the Comms (ASN.1) XML thus is easily verifiable visually, and the output is high quality ASN.1 parsers/serializers.

Dead links in the Readme

The "commsdsl2comms Manual" and "Generated CMake Project Walkthrough" links appear to be dead on the main page

Creating Frame with `id` that is less than one byte

I am working on a protocol where the message id is just 5 bits and remaining 3 bits is part of the message itself.

I couldn't find a way to implement such a thing using the tutorials.

Is there a possibile way to do such a thing?

vcpkg integration

Hey,

I'm currently looking into adding commsdsl and commschampion to vcpkg.
The work is currently here https://github.com/mathisloge/vcpkg/tree/commsdsl

I think it might be a cool addition to this library/tool. What do you think?

Currently i'm stuck configuring the commsdsl repo to use the libcomms built by vcpkg. Is there a way to directly use
find_package(LibComms CONFIG REQUIRED) to use the external commschampion?

This is a bit too hardcoded for vcpkg https://github.com/commschamp/commsdsl/blob/master/CMakeLists.txt#L32

"Unexpected max serialisation length" on variable length field inside variant

Problem

When try to generate code for variant which have variable length field inside, it will generate code, that reports:

/home/jenkins/comms_error2/include/tutorial4/message/Msg2.h:523:29: error: static assertion failed: Unexpected max serialisation length
     static_assert(MsgMaxLen == 257U, "Unexpected max serialisation length");
                   ~~~~~~~~~~^~~~~~~
In file included from /home/jenkins/comms_error2/test/tutorial4_input_test.cpp:12:
/home/jenkins/comms_error2/build/install/include/comms/process.h:119:20: error: ‘comms::ErrorStatus comms::processSingleWithDispatch(TBufIter&, std::size_t, TFrame&&, TMsg&, THandler&, TExtraValues ...) [with TBufIter = char*; TFrame = tutorial4::frame::Frame<comms::Message<comms::option::app::ReadIterator<const char*>, comms::option::app::WriteIterator<char*>, comms::option::app::LengthInfoInterface, comms::option::app::Handler<{anonymous}::Handler>, comms::option::def::Endian<comms::util::traits::endian::Big>, comms::option::def::MsgIdType<tutorial4::MsgId> >, std::tuple<tutorial4::message::Msg1<comms::Message<comms::option::app::ReadIterator<const char*>, comms::option::app::WriteIterator<char*>, comms::option::app::LengthInfoInterface, comms::option::app::Handler<{anonymous}::Handler>, comms::option::def::Endian<comms::util::traits::endian::Big>, comms::option::def::MsgIdType<tutorial4::MsgId> >, tutorial4::options::DefaultOptions>, tutorial4::message::Msg2<comms::Message<comms::option::app::ReadIterator<const char*>, comms::option::app::WriteIterator<char*>, comms::option::app::LengthInfoInterface, comms::option::app::Handler<{anonymous}::Handler>, comms::option::def::Endian<comms::util::traits::endian::Big>, comms::option::def::MsgIdType<tutorial4::MsgId> >, tutorial4::options::DefaultOptions> >, tutorial4::options::DefaultOptions>&; TMsg = std::unique_ptr<comms::Message<comms::option::app::ReadIterator<const char*>, comms::option::app::WriteIterator<char*>, comms::option::app::LengthInfoInterface, comms::option::app::Handler<{anonymous}::Handler>, comms::option::def::Endian<comms::util::traits::endian::Big>, comms::option::def::MsgIdType<tutorial4::MsgId> >, std::default_delete<comms::Message<comms::option::app::ReadIterator<const char*>, comms::option::app::WriteIterator<char*>, comms::option::app::LengthInfoInterface, comms::option::app::Handler<{anonymous}::Handler>, comms::option::def::Endian<comms::util::traits::endian::Big>, comms::option::def::MsgIdType<tutorial4::MsgId> > > >; THandler = {anonymous}::Handler; TExtraValues = {}]’ used but never defined [-Werror]
 comms::ErrorStatus processSingleWithDispatch(

Schema

We use will use original schema from tutorial 4 with slight changes:

<?xml version="1.0" encoding="UTF-8"?>
<schema name="tutorial4" endian="big">
    <fields>
        <string name="Msg1Name" defaultValue="Message 1" />
        <string name="Msg2Name" defaultValue="Message 2" />
            
        <enum name="MsgId" type="uint8" semanticType="messageId">
            <validValue name="M1" val="1" displayName="^Msg1Name" />
            <validValue name="M2" val="2" displayName="^Msg2Name" />
        </enum>
        
        <enum name="PropKey" type="uint8">
            <validValue name="K1" val="0" />
            <validValue name="K2" val="2" />
            <validValue name="K3" val="5" />
            <validValue name="K4" val="10" />
            <validValue name="K5" val="15" />
            <validValue name="K6" val="25" />
        </enum>
        
        <int name="PropKeyCommon" type="uint8" failOnInvalid="true"/>
        
        <variant name="KeyValueProp">
            <bundle name="Prop1">
                <int reuse="PropKeyCommon" name="Key" defaultValue="PropKey.K1" validValue="PropKey.K1" />
                <int name="Val" type="uint16" />
            </bundle>
            
            <bundle name="Prop2">
                <int reuse="PropKeyCommon" name="Key" defaultValue="PropKey.K2" validValue="PropKey.K2" />
                <float name="Val" type="float" defaultValue="nan" />
            </bundle>            
            
            <bundle name="Prop3">
                <int reuse="PropKeyCommon" name="Key" defaultValue="PropKey.K3" validValue="PropKey.K3" />
                <string name="Val">
                    <lengthPrefix>
                        <int name="Length" type="uint8" />
                    </lengthPrefix>
                </string>
            </bundle>    
        </variant>
        
        <variant name="TlvProp">
            <description>
                Type-Length-Value Property
            </description>
            <members>
                <bundle name="Prop4">
                    <int reuse="PropKeyCommon" name="Key" defaultValue="PropKey.K4" validValue="PropKey.K4" />
                    <int name="Length" type="uint8" semanticType="length" />
                    <int name="Val" type="uint32" />
                </bundle>
                
                <bundle name="Prop5">
                    <int reuse="PropKeyCommon" name="Key" defaultValue="PropKey.K5" validValue="PropKey.K5" />
                    <int name="Length" type="uint8" semanticType="length" />
                    <float name="Val" type="double" defaultValue="inf" />
                </bundle>            
                
                <bundle name="Prop6">
                    <int reuse="PropKeyCommon" name="Key" defaultValue="PropKey.K6" validValue="PropKey.K6" />
                    <int name="Length" type="uint8" semanticType="length" />
                    <string name="Val" />
                </bundle>   
                
                <bundle name="Any">
                    <int reuse="PropKeyCommon" name="Key" />
                    <int name="Length" type="uint8" semanticType="length" />
                    <data name="Val" />
                </bundle>  
            </members>
        </variant>
        
    </fields>
    
    <frame name="Frame">
        <size name="Size">
            <int name="SizeField" type="uint16" />
        </size>
        <id name="ID" field="MsgId" />
        <payload name="Data" />
    </frame>
    
    <message name="Msg1" id="MsgId.M1" displayName="^Msg1Name">
        <list name="F1" element="KeyValueProp">
            <countPrefix>
                <int name="Count" type="uint8" />
            </countPrefix>
        </list>
    </message>
    
    <message name="Msg2" id="MsgId.M2" displayName="^Msg2Name">
        <variant reuse="KeyValueProp" />
    </message>      
</schema>

Steps to reproduce

#!/bin/bash

mkdir comms_error2
cd comms_error2
commsdsl2comms ../schema_mod.xml
mkdir build
cd build
cmake -DOPT_BUILD_TEST=ON -DCMAKE_INSTALL_PREFIX=$PWD/install ../
make -j$(nproc --all

Note

What is interesting, when using the same approach but with additional list wrapper around variant - compiles fine.
But whe need to have no additional "number of elements" in our message, just pure variant.

<?xml version="1.0" encoding="UTF-8"?>
<schema name="tutorial4" endian="big">
    <fields>
        <string name="Msg1Name" defaultValue="Message 1" />
        <string name="Msg2Name" defaultValue="Message 2" />
            
        <enum name="MsgId" type="uint8" semanticType="messageId">
            <validValue name="M1" val="1" displayName="^Msg1Name" />
            <validValue name="M2" val="2" displayName="^Msg2Name" />
        </enum>
        
        <enum name="PropKey" type="uint8">
            <validValue name="K1" val="0" />
            <validValue name="K2" val="2" />
            <validValue name="K3" val="5" />
            <validValue name="K4" val="10" />
            <validValue name="K5" val="15" />
            <validValue name="K6" val="25" />
        </enum>
        
        <int name="PropKeyCommon" type="uint8" failOnInvalid="true"/>
        
        <variant name="KeyValueProp">
            <bundle name="Prop1">
                <int reuse="PropKeyCommon" name="Key" defaultValue="PropKey.K1" validValue="PropKey.K1" />
                <int name="Val" type="uint16" />
            </bundle>
            
            <bundle name="Prop2">
                <int reuse="PropKeyCommon" name="Key" defaultValue="PropKey.K2" validValue="PropKey.K2" />
                <float name="Val" type="float" defaultValue="nan" />
            </bundle>            
            
            <bundle name="Prop3">
                <int reuse="PropKeyCommon" name="Key" defaultValue="PropKey.K3" validValue="PropKey.K3" />
                <string name="Val">
                    <lengthPrefix>
                        <int name="Length" type="uint8" />
                    </lengthPrefix>
                </string>
            </bundle>    
        </variant>
        
        <variant name="TlvProp">
            <description>
                Type-Length-Value Property
            </description>
            <members>
                <bundle name="Prop4">
                    <int reuse="PropKeyCommon" name="Key" defaultValue="PropKey.K4" validValue="PropKey.K4" />
                    <int name="Length" type="uint8" semanticType="length" />
                    <int name="Val" type="uint32" />
                </bundle>
                
                <bundle name="Prop5">
                    <int reuse="PropKeyCommon" name="Key" defaultValue="PropKey.K5" validValue="PropKey.K5" />
                    <int name="Length" type="uint8" semanticType="length" />
                    <float name="Val" type="double" defaultValue="inf" />
                </bundle>            
                
                <bundle name="Prop6">
                    <int reuse="PropKeyCommon" name="Key" defaultValue="PropKey.K6" validValue="PropKey.K6" />
                    <int name="Length" type="uint8" semanticType="length" />
                    <string name="Val" />
                </bundle>   
                
                <bundle name="Any">
                    <int reuse="PropKeyCommon" name="Key" />
                    <int name="Length" type="uint8" semanticType="length" />
                    <data name="Val" />
                </bundle>  
            </members>
        </variant>
        
    </fields>
    
    <frame name="Frame">
        <size name="Size">
            <int name="SizeField" type="uint16" />
        </size>
        <id name="ID" field="MsgId" />
        <payload name="Data" />
    </frame>
    
    <message name="Msg1" id="MsgId.M1" displayName="^Msg1Name">
        <list name="F1" element="KeyValueProp">
            <countPrefix>
                <int name="Count" type="uint8" />
            </countPrefix>
        </list>
    </message>
    
    <message name="Msg2" id="MsgId.M2" displayName="^Msg2Name">
        <list name="F2" element="KeyValueProp" />
    </message>      
</schema>

Undefined behaviour on "out of range" values of ID layer.

Setup

  1. add compiler flags:
    -fno-omit-frame-pointer
    -fno-sanitize-recover=undefined
    -fsanitize=undefined
  2. generate code using schema with fixed values for ID frame:
...
    <fields>
        <enum name="CommandType" type="uint8" hexAssign="true">
            <validValue name="TestConnection1" val="27" displayName="Test connection to 1" />
            <validValue name="TestConnection2" val="38" displayName="Test connection to 2" />
        </enum>
    </fields>
...
    <frame name="OurProtocolFrame">
        <id name="Id">
            <field>
                <ref field="CommandType" />
            </field>
        </id>
...
  1. Setup test where comms::processAllWithDispatch is used to dispatch messages, and incoming input has value of ID is way off, for example 68.
  2. Build and run test.

Expected behavior:

Test should pass, without crash, and should notify, that ID value was invalid.

Current behavior:

Test crash with ubsanitizer reporting:
Load of value 68, which is not a valid value for type 'const McuProtocol::MsgId' on line ...
Reporting on line
MsgIdLayer.h#L689

BaseImpl::setMsgId(id, extraValues...)

Specs

Files are "Generated by commsdsl2comms v3.5.2"
compilers:

  • gcc version 8.4.0
  • clang version 8.0.1

Thoughts

Problem occurs because of assignment (cast) of value to the field with enumeration type, with value 68, where enum only happy with 27 and 38.
Current implementation calls

BaseImpl::setMsgId(id, extraValues...); 

Before validation of this value, which trigger ub.
But, even removing that call will not help by itself, because inside of call

msg = createMsgInternal(id, idx, &failureReason);

assignment is done before check, which correctly detects invalid value inside of DispatchMsgStaticBinSearchHelper.h

We have really strict rules about any signs from static/dynamic analysis tools, so we can't just ignore the fact of ubsan reports - that's a pipeline failure.
Wording from standard about static casting to enumeration with "out of range" value.

. I've tried some ad hoc solutions, but it's not easy to grasp all template meta-programming elements, involved in this.
Would really appreciate any temporal bugfixes, which will eliminates this problem.

PS.

In preparing of this issue I've tried to add same flags into root cmake file of this project, and run ctest after it. Your tests reproduce the same kind of problem, but in other place

1/2 Test commschamp/comms_champion#1: comms.FieldsTest .................***Failed   
comms_champion/comms/include/comms/field/adapter/FixedBitLength.h:127:69: runtime error: load of value 4, which is not a valid value for type 'const comms::field::basic::EnumValue<comms::Field<comms::option::def::Endian<comms::util::traits::endian::Big> >, FieldsTestSuite::Enum1>::ValueType' (aka 'const FieldsTestSuite::Enum1')
2: 
2: CMake Error at comms_champion/cmake/CC_RunWithValgrindScript.cmake:30 (message):
2:   Test failed with exit code 1

@arobenko if you want I can open another issue about sanitizers (address santizier give even more errors) and tests.

But our main focus is on dealing with ID field problem.

Schema name cannot start with a capital

I have had an issue with two different protocol definitions where I started the name of the schema file with a capital letter. This is in contrast with the given examples in the documentation and should not be a limitation:

image

The generated code wants to refer to the namespace that is defined by the schema name. However, the namespace starts with a lowercase letter:

image

The resulting compilation errors are also not that obvious, since template issues can cause quite a lenghty report.

Bit Order in `<bitfield>` and `<set>`

I've defined a <bitfield> in the XML.

image

As I set flag F to true, this is what I get in Wireshark:

image

With endian="big", this is what I get:

image

Another thing is when I try to modify the value of UnitNum field, I actually change the value of PXNum field.

With msg.field_annFlags().field_unitNum().value() = 1:

image

How to alter the bit order of generated packet data?

Select variant based on value in the transport frame

I am modeling a protocol that contains a request-reply pattern, where the payload of the reply can only be identified by an identifier that the clients puts into the transport frame of the request. In other words, I can decode the reply based on information that is ony known by the client and echoed by the the server.

I first did some manual decoding of the payload, but then I end up doing the same stuff where comms is the champ ;-) So, I modeled that as well in commsdsl, in the form:

<variant>
  <bundle/>
  <bundle/>
  <bundle/>
</variant>

I studied the commsdsl manual and tutorial4 of the cc_tutorials. However, me payload has no key to identify what variant to select. I tried the following two approaches, but failed to get it to work:

  1. Insert a 'pseudo' key into the bundles with a 'validValue' identical to the key that is found in the transport frame value. Then copy the transport frame value into the pseudo element during dispatching and then rely on the 'currentFieldExec' method as done in tutorial4.
  2. Insert a 'pseudo' key into the bundled with a 'defaultValue'. Then iterate over all members of the variant during dispatching and compare the transport frame value to each defaultValue. Keep the member field selected that matches with the transport frame value.

Before this I modeled this variant with a sequence of 'optional' fields. While this is conceptually wrong, it did work because in the condition I can refer to the transport frame value.

I hope somebody could point me in the right direction. Should I stick with the 'variant' or go with the 'optional' values? If 'variant' is the way to go, how can I ensure that the variant member is selected based on information in the transport frame?

`optional` field with `cond` depending on another `optional` field.

Hi, I have the following schema definition:

<optional name="OFRQ8_14" cond="$FRQ1_7.FX">
  <set name="FRQ8_14" length="1">
      <bit name="FRN8" idx="7" />
      <bit name="FRN9" idx="6" />
      <bit name="FRN10" idx="5" />
      <bit name="FRN11" idx="4" />
      <bit name="FRN12" idx="3" />
      <bit name="FRN13" idx="2" />
      <bit name="FRN14" idx="1" />
      <bit name="FX" idx="0" />
  </set>
</optional>
<optional name="OFRQ15_21" cond="$OFRQ8_14.FRQ8_14.FX">
  <set name="FRQ15_21" length="1">
      <bit name="FRN15" idx="7" />
      <bit name="FRN16" idx="6" />
      <bit name="FRN17" idx="5" />
      <bit name="FRN18" idx="4" />
      <bit name="FRN19" idx="3" />
      <bit name="FRN20" idx="2" />
      <bit name="FRN21" idx="1" />
      <bit name="FX" idx="0" />
  </set>
</optional>

where the OFRQ15_21 field depends on an inner field within OFRQ8_14.

However it keeps complaining the it needs to be an existing field.

How can I make this work. It makes sense to me that I test the existence of the first optional field first. How can I do this?

Question: List without length and message size

Imagine a very simple protocol:

|id|payload|crc|
(1byte | unlimited | 1 byte)

When i have a list with just int8 types without a prefixed size, the status returned by processSingle is every time NotEnoughData.
I know the size of the complete message at the beginning. is there a way to specify the possible max len of the list?

<message>
  <list name="XList">
      <int name="X" type="int8" />
  </list>
</message>

error when using COMMSDSL_NO_TESTS

When setting the option COMMSDSL_NO_TESTS to true, the tests in lib/test cmake are still executed.
setting BUILD_TESTING to false if COMMSDSL_NO_TESTS is true fixes the issue for me

Can a (serial) protocol with character escaping be realized using the custom code feature?

I have a character-based protocol with a STX and ETX character, and where the payload is escaped with an escape character. I have a working protocol encoder/decoder using commsdsl. But I have not been able to do the frame reading/writing using this framework.

As a workaround I have the following:

<frame name="ProtocolFrame"> <layers> <!--<sync name="STX"> <int name="SyncField" type="uint8" defaultValue="0x55"> <validValue value="0x55"/> <failOnInvalid value="true"/> </int> </sync>--> <id name="cmd" field="cmd"/> <payload name="Data"/> <checksum name="CRC" alg="custom" algName="CRC8DallasMaxim" from="uC"> <int name="CRCField" type="uint8"/> </checksum> <!-- <custom name="ETX" semanticLayerType="value"> <ref name="etx" field="etx"/> </custom> --> </layers> </frame>

In my own C++ code I do the (un)escaping, and the STX/ETX handling before and after the commsdsl frame handling. Works fine, but I would like to know the framework better to see if I can improve on this.
So, can I customize the frame reading/writing to peform the character escaping before and after the frame encoding and decoding?

Field Extension Support in Lists with termSuffix

I have the following protocol definition:

<bundle name="DataItem100" displayName="Processing Status" description="Information concerning the scaling factor currently applied, current reduction step in use, etc.">
    <bitfield name="B24_1">
        <set name="FX" bitLength="1">
            <bit name="fx" displayName="Field extension" idx="0" />
        </set>
        <int name="Q" displayName="Processing parameters" type="uint16" bitLength="15" />
        <enum name="R" displayName="Current reduction stage" type="uint8" bitLength="3">
            <validValue name="NormalOperation" displayName="Normal operation" val="0" />
        </enum>
        <int name="f" displayName="Scaling factor f" type="uint8" bitLength="5" />
    </bitfield>
</bundle>

This bundle can be repeated until the fx field is set to 0. I think this is a common occurrence in many protocols.

I would love it if either of the two following solutions is possible:
1: temSuffix for list is bit wise not byte wise.
2: lists support cond like optional.

Adding constexpr to static const functions

The name() function seems to always return a pointer to a compile time defined string. It has the following signature:
static const char* name();

I see no reason it should not be possible to add constexpr to the name functions other than backwards compatibility issues. Adding constexpr would enable the use of the function in compile time initialization of parameters in user code. Now it is not possible to do so which means duplication of name definitions. The same name thus must be defined in the schema file and in the c++ sources.

My intended use is as follows:

struct Xml_tags
{
    using Max_qos = mqtt5::field::SubscribeOptionsMembersCommon::MaxQosCommon;
    constexpr char static * max_qos = Max_qos::name();
    // More tags follows
};

Need Help

Hey sorry for interrupting you again, but i dont know how to proceed. I have already two custom protocols implemented but the third isnt working and i dont know why. Ive prepared a simple
demo:
Schema:

<?xml version="1.0" encoding="UTF-8"?>
<schema name="MyProtocol" endian="big">
	<fields>
        <enum name="MsgId" type="uint8" semanticType="messageId" >
            <validValue name="TestId" val="0" />
        </enum>
    </fields>

	<interface name="FrameInterface">
    </interface>
	<frame name="Frame">
        <sync name="Sync">
            <int name="Sync" type="uint16" defaultValue="0xabcd" validValue="0xabcd" failOnInvalid="true"/>
        </sync>
        <size name="Size">
            <int name="Size" type="uint16" serOffset="4" displayOffset="4"/>
        </size>
        <id name="Id" field="MsgId" />
        <payload name="Data" />
		<checksum name="Checksum" alg="sum " from="Size">
            <int name="Checksum" type="uint16" />
        </checksum>
    </frame>       
	
	<message name="TestPoll" id="MsgId.TestId">
		<int name="TestField" type="uint8"/>
    </message>
</schema>

Definitions:


using InMessage =
          MyProtocol::FrameInterface<
              comms::option::ReadIterator<const std::uint8_t*>,
              comms::option::Handler<Application>,
              comms::option::NameInterface
         >;

     using InPollTest= MyProtocol::message::TestPoll<InMessage>;
     using AllInMessages = std::tuple<InPollTest>;
     using Frame = MyProtocol::frame::Frame<InMessage, AllInMessages>;
     using OutputMsg =
             MyProtocol::FrameInterface<
                 comms::option::WriteIterator<std::back_insert_iterator<std::vector<std::uint8_t> > >,
                 comms::option::LengthInfoInterface,
                 comms::option::IdInfoInterface,
                 comms::option::NameInterface
             >;
     Frame frame;

Test code:

MyProtocol::message::TestPoll<OutputMsg> msg;
    std::vector<std::uint8_t> outputBuf;
    outputBuf.reserve(frame.length(msg));
    auto iter = std::back_inserter(outputBuf);
    auto es = frame.write(msg, iter, outputBuf.max_size());
    if (es == comms::ErrorStatus::UpdateRequired) {
        auto updateIter = &outputBuf[0];
        es = frame.update(updateIter, outputBuf.size());
    }

    if (es != comms::ErrorStatus::Success) {
        UARTprintf("\nUnexpected error\n");
        return;
    }
    UARTprintf("TX:\n");
    for(int i = 0; i < outputBuf.size(); i++) {
        UARTprintf("%x ", outputBuf[i]);
    }
    UARTprintf("\nCONSUME:\n");

        const auto consumed = comms::processAllWithDispatch(&outputBuf[0],
                                                            outputBuf.size(),
                                                            frame,
                                                            *this);
       UARTprintf("RX:");
       for(auto i = 0; i < outputBuf.size(); i++)
       {
           UARTprintf("%x ", outputBuf[i]);
       }
       UARTprintf("---%i\n", consumed);
       if(consumed != outputBuf.size()) {
          LOG_ERROR("Something is wrong...");
       }

The Error-Code is on "InvalidMsgId"

Ive inserted some DebugMessages but cant find the root cause:

DEBUG | MsgIdLayer.h | doReadInternal():681 | 5
DEBUG | MsgFactoryBase.h | createMsgInternal():427 | VIRTUAL
DEBUG | MsgFactoryBase.h | dispatchMsgTypeInternal():364 | StandardTag
DEBUG | dispatch.h | dispatchMsgType():490 | Complex
DEBUG | dispatch.h | dispatchMsgTypeInternal():578 | PolymorphicTag
DEBUG | DispatchMsgPolymorphicHelper.h | dispatch():1074 | offset 0 1
DEBUG | DispatchMsgPolymorphicHelper.h | dispatchInternal():1115 | DirectTag 0
DEBUG | DispatchMsgPolymorphicHelper.h | dispatchInternal():1102 | DirectTag
DEBUG | DispatchMsgPolymorphicHelper.h | dispatch():895 | regIdx 0
DEBUG | DispatchMsgPolymorphicHelper.h | dispatch():897 | regIdx 0
DEBUG | MsgFactoryBase.h | createMsgInternal():430 | Success: 0
DEBUG | MsgFactoryBase.h | createMsg():168 | 0
DEBUG | MsgIdLayer.h | doReadInternal():687 | 1, 0, 0
RX:ab cd 0 6 0 0 0 6 ---8

Where is my mistake? I just cant see it.

Optional condition doesnt work with ref field

Optional condition doesnt work, if the reference field is of type ref which points to a set.

Example:

<fields>

<set name="InfoTypes" length="8">

<bit name="TransponderPosition" idx="0" />

<bit name="GPSPos" idx="1" />

  </set>

</fields>

 

<message …>

 

<fields>

 <ref field="InfoTypes"/>

 

<optional name="TransponderPosition" defaultMode="exists" cond="$InfoTypes.TransponderPosition">

<ref field="PositionCoords"/>

</optional>

</fields>

  </message>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.