Skip to content

Commit 07ad4fc

Browse files
committed
Detecting sequence of escape fields in SyncPrefixLayer and SyncSuffixLayer.
1 parent 34b7724 commit 07ad4fc

4 files changed

Lines changed: 176 additions & 44 deletions

File tree

include/comms/frame/SyncPrefixLayer.h

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -316,38 +316,52 @@ class SyncPrefixLayer : public comms::frame::details::SyncPrefixLayerBase<TField
316316
template <typename TIter>
317317
bool fieldEscapedInternal(TIter from, TIter to, EscapeSupportedTag<>)
318318
{
319-
auto dist = static_cast<std::size_t>(std::distance(from, to));
320-
dist = std::min(dist, EscField::maxLength());
321-
if (dist < EscField::minLength()) {
322-
return false;
323-
}
324-
319+
unsigned escCount = 0U;
325320
auto& thisObj = BaseImpl::thisLayer();
326321

327-
auto limitIter = to;
328-
std::advance(limitIter, -static_cast<int>(dist));
322+
while (from != to) {
323+
auto dist = static_cast<std::size_t>(std::distance(from, to));
324+
dist = std::min(dist, EscField::maxLength());
325+
if (dist < EscField::minLength()) {
326+
break;
327+
}
329328

330-
auto iter = to;
331-
std::advance(iter, -static_cast<int>(EscField::minLength()));
332-
while (true) {
333-
auto iterTmp = iter;
334-
EscField escField;
335-
auto len = static_cast<std::size_t>(std::distance(iterTmp, to));
336-
auto es = escField.read(iterTmp, len);
337-
if ((es == comms::ErrorStatus::Success) &&
338-
(iterTmp == to) &&
339-
(thisObj.verifyEscFieldValue(escField))) {
340-
return true;
329+
auto maxLenIter = to;
330+
std::advance(maxLenIter, -static_cast<int>(dist));
331+
332+
auto iter = to;
333+
std::advance(iter, -static_cast<int>(EscField::minLength()));
334+
auto prevCount = escCount;
335+
while (true) {
336+
auto iterTmp = iter;
337+
EscField escField;
338+
auto len = static_cast<std::size_t>(std::distance(iterTmp, to));
339+
auto es = escField.read(iterTmp, len);
340+
if ((es == comms::ErrorStatus::Success) &&
341+
(iterTmp == to) &&
342+
(thisObj.verifyEscFieldValue(escField))) {
343+
++escCount;
344+
break;
345+
}
346+
347+
if (iter == maxLenIter) {
348+
break;
349+
}
350+
351+
std::advance(iter, -1);
341352
}
342353

343-
if (iter == limitIter) {
354+
if (prevCount == escCount) {
355+
// Failed to detect escField
344356
break;
345357
}
346358

347-
std::advance(iter, -1);
359+
// esc field was detected, trying again
360+
to = iter;
348361
}
349362

350-
return false;
363+
// Escaped only if odd number of esc field is detected
364+
return (escCount & 0x1) != 0U;
351365
}
352366

353367
template <typename TIter>

include/comms/frame/SyncSuffixLayer.h

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -583,38 +583,52 @@ class SyncSuffixLayer : public comms::frame::details::SyncSuffixLayerBase<TField
583583
template <typename TIter>
584584
bool fieldEscapedInternal(TIter from, TIter to, EscapeSupportedTag<>)
585585
{
586-
auto dist = static_cast<std::size_t>(std::distance(from, to));
587-
dist = std::min(dist, EscField::maxLength());
588-
if (dist < EscField::minLength()) {
589-
return false;
590-
}
591-
586+
unsigned escCount = 0U;
592587
auto& thisObj = BaseImpl::thisLayer();
593588

594-
auto limitIter = to;
595-
std::advance(limitIter, -static_cast<int>(dist));
589+
while (from != to) {
590+
auto dist = static_cast<std::size_t>(std::distance(from, to));
591+
dist = std::min(dist, EscField::maxLength());
592+
if (dist < EscField::minLength()) {
593+
break;
594+
}
596595

597-
auto iter = to;
598-
std::advance(iter, -static_cast<int>(EscField::minLength()));
599-
while (true) {
600-
auto iterTmp = iter;
601-
EscField escField;
602-
auto len = static_cast<std::size_t>(std::distance(iterTmp, to));
603-
auto es = escField.read(iterTmp, len);
604-
if ((es == comms::ErrorStatus::Success) &&
605-
(iterTmp == to) &&
606-
(thisObj.verifyEscFieldValue(escField))) {
607-
return true;
596+
auto maxLenIter = to;
597+
std::advance(maxLenIter, -static_cast<int>(dist));
598+
599+
auto iter = to;
600+
std::advance(iter, -static_cast<int>(EscField::minLength()));
601+
auto prevCount = escCount;
602+
while (true) {
603+
auto iterTmp = iter;
604+
EscField escField;
605+
auto len = static_cast<std::size_t>(std::distance(iterTmp, to));
606+
auto es = escField.read(iterTmp, len);
607+
if ((es == comms::ErrorStatus::Success) &&
608+
(iterTmp == to) &&
609+
(thisObj.verifyEscFieldValue(escField))) {
610+
++escCount;
611+
break;
612+
}
613+
614+
if (iter == maxLenIter) {
615+
break;
616+
}
617+
618+
std::advance(iter, -1);
608619
}
609620

610-
if (iter == limitIter) {
621+
if (prevCount == escCount) {
622+
// Failed to detect escField
611623
break;
612624
}
613625

614-
std::advance(iter, -1);
626+
// esc field was detected, trying again
627+
to = iter;
615628
}
616629

617-
return false;
630+
// Escaped only if odd number of esc field is detected
631+
return (escCount & 0x1) != 0U;
618632
}
619633

620634
template <typename TIter>

test/SyncPrefixLayer.th

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public:
3030
void test8();
3131
void test9();
3232
void test10();
33+
void test11();
34+
void test12();
3335

3436
private:
3537

@@ -455,6 +457,66 @@ void SyncPrefixLayerTestSuite::test10()
455457

456458
static const std::size_t BufSize = std::extent<decltype(Buf)>::value;
457459

460+
using TestFrame =
461+
SeekFieldWithEscFrame<
462+
BeSyncField2,
463+
BeEscField2,
464+
BeSizeField20,
465+
BeIdField1,
466+
BeMsgBase
467+
>;
468+
469+
TestFrame frame;
470+
TestFrame::MsgPtr msg;
471+
auto readIter = comms::readIteratorFor(msg, Buf);
472+
auto es = frame.read(msg, readIter, BufSize);
473+
TS_ASSERT_EQUALS(es, comms::ErrorStatus::Success);
474+
TS_ASSERT(msg);
475+
TS_ASSERT_EQUALS(msg->getId(), MessageType1);
476+
auto& msg1 = dynamic_cast<BeMsg1&>(*msg);
477+
TS_ASSERT_EQUALS(std::get<0>(msg1.fields()).value(), 0x0102);
478+
}
479+
480+
void SyncPrefixLayerTestSuite::test11()
481+
{
482+
static const char Buf[] = {
483+
0x0, 0x1, static_cast<char>(0xde), static_cast<char>(0xad), static_cast<char>(0xde), static_cast<char>(0xad), // double esc
484+
static_cast<char>(0xab), static_cast<char>(0xcd), 0x0, 0x3, MessageType1, 0x01, 0x02, static_cast<char>(0x3f)
485+
};
486+
487+
static const std::size_t BufSize = std::extent<decltype(Buf)>::value;
488+
489+
using TestFrame =
490+
SeekFieldWithEscFrame<
491+
BeSyncField2,
492+
BeEscField2,
493+
BeSizeField20,
494+
BeIdField1,
495+
BeMsgBase
496+
>;
497+
498+
TestFrame frame;
499+
TestFrame::MsgPtr msg;
500+
auto readIter = comms::readIteratorFor(msg, Buf);
501+
auto es = frame.read(msg, readIter, BufSize);
502+
TS_ASSERT_EQUALS(es, comms::ErrorStatus::Success);
503+
TS_ASSERT(msg);
504+
TS_ASSERT_EQUALS(msg->getId(), MessageType1);
505+
auto& msg1 = dynamic_cast<BeMsg1&>(*msg);
506+
TS_ASSERT_EQUALS(std::get<0>(msg1.fields()).value(), 0x0102);
507+
}
508+
509+
void SyncPrefixLayerTestSuite::test12()
510+
{
511+
static const char Buf[] = {
512+
0x0, 0x1, static_cast<char>(0xde), static_cast<char>(0xad),
513+
static_cast<char>(0xde), static_cast<char>(0xad),
514+
static_cast<char>(0xde), static_cast<char>(0xad), static_cast<char>(0xab), static_cast<char>(0xcd), // garbage with triple esc
515+
static_cast<char>(0xab), static_cast<char>(0xcd), 0x0, 0x3, MessageType1, 0x01, 0x02, static_cast<char>(0x3f)
516+
};
517+
518+
static const std::size_t BufSize = std::extent<decltype(Buf)>::value;
519+
458520
using TestFrame =
459521
SeekFieldWithEscFrame<
460522
BeSyncField2,

test/SyncSuffixLayer.th

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ public:
2424
void test2();
2525
void test3();
2626
void test4();
27+
void test5();
28+
void test6();
2729

2830
private:
2931

@@ -200,3 +202,43 @@ void SyncSuffixLayerTestSuite::test4()
200202
TS_ASSERT_EQUALS(std::get<0>(msg11.fields()).value(), "he@@==llo");
201203
}
202204

205+
void SyncSuffixLayerTestSuite::test5()
206+
{
207+
// Double esc field should be ignored
208+
static const char Buf[] = {
209+
MessageType11, 'h', 'e', 'l', 'l', 'o', '@', '@', '@', '@', '=', '=', static_cast<char>(0x3f)
210+
};
211+
212+
static const std::size_t BufSize = std::extent<decltype(Buf)>::value;
213+
214+
SeekFieldWithEscFrame frame;
215+
SeekFieldWithEscFrame::MsgPtr msg;
216+
auto readIter = comms::readIteratorFor(msg, Buf);
217+
auto es = frame.read(msg, readIter, BufSize);
218+
TS_ASSERT_EQUALS(es, comms::ErrorStatus::Success);
219+
TS_ASSERT(msg);
220+
TS_ASSERT_EQUALS(msg->getId(), MessageType11);
221+
auto& msg11 = dynamic_cast<BeMsg11&>(*msg);
222+
TS_ASSERT_EQUALS(std::get<0>(msg11.fields()).value(), "hello@@@@");
223+
}
224+
225+
void SyncSuffixLayerTestSuite::test6()
226+
{
227+
// Triple escape should still count as escape
228+
static const char Buf[] = {
229+
MessageType11, 'h', 'e', '@', '@', '@', '@', '@', '@', '=', '=', 'l', 'l', 'o', '=', '=', static_cast<char>(0x3f)
230+
};
231+
232+
static const std::size_t BufSize = std::extent<decltype(Buf)>::value;
233+
234+
SeekFieldWithEscFrame frame;
235+
SeekFieldWithEscFrame::MsgPtr msg;
236+
auto readIter = comms::readIteratorFor(msg, Buf);
237+
auto es = frame.read(msg, readIter, BufSize);
238+
TS_ASSERT_EQUALS(es, comms::ErrorStatus::Success);
239+
TS_ASSERT(msg);
240+
TS_ASSERT_EQUALS(msg->getId(), MessageType11);
241+
auto& msg11 = dynamic_cast<BeMsg11&>(*msg);
242+
TS_ASSERT_EQUALS(std::get<0>(msg11.fields()).value(), "he@@@@@@==llo");
243+
}
244+

0 commit comments

Comments
 (0)