Skip to content

Commit 15f81ae

Browse files
committed
README for tutorial24.
1 parent 389ca5f commit 15f81ae

File tree

2 files changed

+118
-3
lines changed

2 files changed

+118
-3
lines changed

tutorials/tutorial24/README.md

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,123 @@
11
# Tutorial 24
22
Extra validity verification of message payload.
33

4+
Many protocols specify extra validity conditions of the message payload. For example,
5+
some fields require having (or not having) certain values base on the value of other fields.
6+
The [CommsDSL](https://github.com/commschamp/CommsDSL-Specification) allows specify such conditions
7+
using **validCond** property. It works in exactly the same way as **construct** and/or **readCond** ones
8+
described in the [tutorial16](../tutorial23) (including referencing the interface fields if needed).
49

5-
## Summary
10+
The [schema](dsl/schema.xml) of this tutorial has `Msg1` defined as below:
11+
12+
```xml
13+
<message name="Msg1" id="MsgId.M1" ...>
14+
<fields>
15+
<int name="F1" type="uint8" />
16+
<int name="F2" type="uint8" />
17+
</fields>
18+
<validCond>
19+
<or>
20+
<validCond value="$F1 != 0" />
21+
<validCond value="$F2 = 0" />
22+
</or>
23+
</validCond>
24+
</message>
25+
```
26+
In this example `F2` must be `0` in case `F1` is `0`.
27+
28+
The generated [Msg1](include/tutorial24/message/Msg1.h) implements its `doValid()` member function accordingly:
29+
```cpp
30+
template <typename TMsgBase, typename TOpt = tutorial24::options::DefaultOptions>
31+
class Msg1 : public
32+
comms::MessageBase<...>
33+
{
34+
...
35+
36+
// Generated validity check functionality
37+
bool doValid() const
38+
{
39+
if (!Base::doValid()) {
40+
return false;
41+
}
42+
43+
return
44+
((field_f1().getValue() != static_cast<typename Field_f1::ValueType>(0U)) ||
45+
(field_f2().getValue() == static_cast<typename Field_f2::ValueType>(0U)));
46+
}
47+
};
48+
```
49+
50+
In some cases the protocol specification demands the message to be discarded if its contents are invalid.
51+
The [CommsDSL](https://github.com/commschamp/CommsDSL-Specification) provides **failOnInvalid** property that
52+
can be used for messages, not only fields.
53+
54+
```xml
55+
<message name="Msg1" id="MsgId.M1" failOnInvalid="true" displayName="^Msg1Name">
56+
...
57+
</message>
58+
```
59+
60+
The generated [Msg1](include/tutorial24/message/Msg1.h) class uses **comms::option::def::FailOnInvalid** option in the
61+
message class definition.
62+
```
63+
template <typename TMsgBase, typename TOpt = tutorial24::options::DefaultOptions>
64+
class Msg1 : public
65+
comms::MessageBase<
66+
TMsgBase,
67+
comms::option::def::StaticNumIdImpl<tutorial24::MsgId_M1>,
68+
comms::option::def::FieldsImpl<typename Msg1Fields<TOpt>::All>,
69+
comms::option::def::MsgType<Msg1<TMsgBase, TOpt> >,
70+
comms::option::def::HasName,
71+
comms::option::def::FailOnInvalid<>
72+
>
73+
{...};
74+
```
675

76+
The code which prepares and sends `Msg1` inside the [src/ClientSession.cpp](src/ClientSession.cpp) looks like this:
77+
```cpp
78+
void ClientSession::sendMsg1()
79+
{
80+
Msg1 msg;
81+
assert(msg.doValid());
82+
83+
msg.field_f2().value() = 2;
84+
assert(!msg.doValid());
85+
sendMessage(msg); // Invalid message can be sent, but should be ignored on reception
86+
87+
msg.field_f1().value() = 1;
88+
sendMessage(msg); // Should get received and echoed back
89+
}
90+
```
91+
Note that `Msg1` is sent twice. When the message contents are invalid the object gets discarded on the server side and only
92+
the valid one is echoes back to the client.
93+
94+
The **failOnInvalid** property assigned to the `<message>` works also without any extra validity conditions (**validCond**) in
95+
case any of the fields contain invalid values:
96+
```xml
97+
<message name="Msg2" id="MsgId.M2" failOnInvalid="true" displayName="^Msg2Name">
98+
<int name="F1" type="uint8" validRange="[0, 10]" />
99+
<int name="F2" type="uint8" validRange="[10, 20]" />
100+
</message>
101+
```
102+
103+
The code which sends/receives `Msg2` demonstrates it:
104+
```cpp
105+
void ClientSession::sendMsg2()
106+
{
107+
Msg2 msg;
108+
assert(!msg.doValid()); // F2 is invalid when default constructed
109+
sendMessage(msg); // Invalid message can be sent, but should be ignored on reception
110+
111+
msg.field_f1().value() = 5;
112+
msg.field_f2().value() = 10;
113+
assert(msg.doValid());
114+
sendMessage(msg); // Should get received and echoed back
115+
}
116+
```
117+
118+
## Summary
119+
- To specify extra validity condition(s) use **validCond** property (or **&lt;validCond&gt;** child node).
120+
- The **validCond** property uses the same syntax / rules as **construct** and **readCond** described in [tutorial16](../tutorial16).
121+
- To discard message on invalid contents use **failOnInvalid** property.
7122

8123
[Read Previous Tutorial](../tutorial23) &lt;-----------------------

tutorials/tutorial24/src/ClientSession.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,12 @@ void ClientSession::sendMsg2()
145145
{
146146
Msg2 msg;
147147
assert(!msg.doValid()); // F2 is invalid when default constructed
148-
149148
sendMessage(msg); // Invalid message can be sent, but should be ignored on reception
150149

151150
msg.field_f1().value() = 5;
152151
msg.field_f2().value() = 10;
153-
sendMessage(msg);
152+
assert(msg.doValid());
153+
sendMessage(msg); // Should get received and echoed back
154154
}
155155

156156
SessionPtr Session::createClient(boost_wrap::io& io)

0 commit comments

Comments
 (0)