Skip to content
This repository has been archived by the owner on Sep 1, 2022. It is now read-only.

Commit

Permalink
Really fix #138.
Browse files Browse the repository at this point in the history
  • Loading branch information
emgre committed Apr 23, 2020
1 parent f65cce6 commit 60b6bfd
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 36 deletions.
35 changes: 18 additions & 17 deletions cpp/lib/src/link/PriLinkLayerStates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ PriStateBase& PriStateBase::TrySendRequestLinkStatus(LinkContext& /*unused*/)
}

////////////////////////////////////////////////////////
// Class PLLS_SecNotResetIdle
// Class PLLS_SecNotResetIdle
////////////////////////////////////////////////////////

PLLS_Idle PLLS_Idle::instance;
Expand All @@ -100,11 +100,12 @@ PriStateBase& PLLS_Idle::TrySendRequestLinkStatus(LinkContext& ctx)
ctx.keepAliveTimeout = false;
ctx.QueueRequestLinkStatus(ctx.config.RemoteAddr);
ctx.listener->OnKeepAliveInitiated();
return PLLS_RequestLinkStatusTransmitWait::Instance();
ctx.StartResponseTimer();
return PLLS_RequestLinkStatusWait::Instance();
}

////////////////////////////////////////////////////////
// Class SendUnconfirmedTransmitWait
// Class SendUnconfirmedTransmitWait
////////////////////////////////////////////////////////

PLLS_SendUnconfirmedTransmitWait PLLS_SendUnconfirmedTransmitWait::instance;
Expand All @@ -124,25 +125,19 @@ PriStateBase& PLLS_SendUnconfirmedTransmitWait::OnTxReady(LinkContext& ctx)
return PLLS_Idle::Instance();
}

/////////////////////////////////////////////////////////////////////////////
// Wait for the link layer to transmit the request link status
/////////////////////////////////////////////////////////////////////////////

PLLS_RequestLinkStatusTransmitWait PLLS_RequestLinkStatusTransmitWait::instance;

PriStateBase& PLLS_RequestLinkStatusTransmitWait::OnTxReady(LinkContext& ctx)
{
// now we're waiting on a LINK_STATUS
ctx.StartResponseTimer();
return PLLS_RequestLinkStatusWait::Instance();
}

////////////////////////////////////////////////////////
// Class PLLS_RequestLinkStatusWait
// Class PLLS_RequestLinkStatusWait
////////////////////////////////////////////////////////

PLLS_RequestLinkStatusWait PLLS_RequestLinkStatusWait::instance;

PriStateBase& PLLS_RequestLinkStatusWait::OnAck(LinkContext& ctx, bool /*receiveBuffFull*/)
{
ctx.CancelTimer();
ctx.FailKeepAlive(false);
return PLLS_Idle::Instance();
}

PriStateBase& PLLS_RequestLinkStatusWait::OnNack(LinkContext& ctx, bool /*receiveBuffFull*/)
{
ctx.CancelTimer();
Expand All @@ -164,6 +159,12 @@ PriStateBase& PLLS_RequestLinkStatusWait::OnNotSupported(LinkContext& ctx, bool
return PLLS_Idle::Instance();
}

PriStateBase& PLLS_RequestLinkStatusWait::OnTxReady(LinkContext& ctx)
{
// The request link status was successfully sent
return *this;
}

PriStateBase& PLLS_RequestLinkStatusWait::OnTimeout(LinkContext& ctx)
{
SIMPLE_LOG_BLOCK(ctx.logger, flags::WARN, "Link status request - response timeout");
Expand Down
21 changes: 6 additions & 15 deletions cpp/lib/src/link/PriLinkLayerStates.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@ class PLLS_Idle final : public PriStateBase
{
MACRO_STATE_SINGLETON_INSTANCE(PLLS_Idle);

virtual PriStateBase& TrySendUnconfirmed(LinkContext&, ITransportSegment& segments) override;
virtual PriStateBase& TrySendRequestLinkStatus(LinkContext&) override;
PriStateBase& TrySendUnconfirmed(LinkContext&, ITransportSegment& segments) override;
PriStateBase& TrySendRequestLinkStatus(LinkContext&) override;
};

/////////////////////////////////////////////////////////////////////////////
// template wait state for send unconfirmed data
// Wait state for send unconfirmed data
/////////////////////////////////////////////////////////////////////////////

class PLLS_SendUnconfirmedTransmitWait final : public PriStateBase
Expand All @@ -70,28 +70,19 @@ class PLLS_SendUnconfirmedTransmitWait final : public PriStateBase
};

/////////////////////////////////////////////////////////////////////////////
// Waiting for a link status transmission
/////////////////////////////////////////////////////////////////////////////

class PLLS_RequestLinkStatusTransmitWait : public PriStateBase
{
MACRO_STATE_SINGLETON_INSTANCE(PLLS_RequestLinkStatusTransmitWait);

virtual PriStateBase& OnTxReady(LinkContext& ctx) override;
};

/////////////////////////////////////////////////////////////////////////////
// Waiting for a link status response
// Waiting for a link status response
/////////////////////////////////////////////////////////////////////////////

// @section desc As soon as we get an ACK, send the delayed pri frame
class PLLS_RequestLinkStatusWait final : public PriStateBase
{
MACRO_STATE_SINGLETON_INSTANCE(PLLS_RequestLinkStatusWait);

PriStateBase& OnAck(LinkContext& ctx, bool) override;
PriStateBase& OnNack(LinkContext& ctx, bool) override;
PriStateBase& OnLinkStatus(LinkContext& ctx, bool) override;
PriStateBase& OnNotSupported(LinkContext& ctx, bool) override;
PriStateBase& OnTxReady(LinkContext&) override;
PriStateBase& OnTimeout(LinkContext&) override;
};

Expand Down
75 changes: 71 additions & 4 deletions cpp/tests/unit/TestLinkLayerKeepAlive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,30 @@ TEST_CASE(SUITE("ForwardsKeepAliveTimeouts"))
REQUIRE(t.listener->numKeepAliveTransmissions == 1);
}

TEST_CASE(SUITE("KeepAliveFailureCallbackIsInvokedOnTimeout"))
TEST_CASE(SUITE("KeepAliveStopsOnAck"))
{
LinkConfig config(true, false);
config.KeepAliveTimeout = TimeDuration::Seconds(5);
LinkLayerTest t(config);

t.link.OnLowerLayerUp();

REQUIRE(t.exe->num_pending_timers() == 1);
REQUIRE(t.listener->numKeepAliveTransmissions == 0);

REQUIRE(t.exe->advance_to_next_timer());
REQUIRE(t.exe->run_many() > 0);

REQUIRE(t.PopLastWriteAsHex() == LinkHex::RequestLinkStatus(true, 1024, 1));
REQUIRE(t.exe->num_pending_timers() == 2);
t.link.OnTxReady();
REQUIRE(t.exe->num_pending_timers() == 2);
t.OnFrame(LinkFunction::SEC_ACK, false, false, false, 1, 1024);
REQUIRE(t.exe->num_pending_timers() == 1);
REQUIRE(t.listener->numKeepAliveFailure == 0); // Not reported as a failure, because there is activity on the link
}

TEST_CASE(SUITE("KeepAliveStopsOnNack"))
{
LinkConfig config(true, false);
config.KeepAliveTimeout = TimeDuration::Seconds(5);
Expand All @@ -75,7 +98,30 @@ TEST_CASE(SUITE("KeepAliveFailureCallbackIsInvokedOnTimeout"))
REQUIRE(t.exe->run_many() > 0);

REQUIRE(t.PopLastWriteAsHex() == LinkHex::RequestLinkStatus(true, 1024, 1));
REQUIRE(t.exe->num_pending_timers() == 2);
t.link.OnTxReady();
REQUIRE(t.exe->num_pending_timers() == 2);
t.OnFrame(LinkFunction::SEC_NACK, false, false, false, 1, 1024);
REQUIRE(t.exe->num_pending_timers() == 1);
REQUIRE(t.listener->numKeepAliveFailure == 0); // Not reported as a failure, because there is activity on the link
}

TEST_CASE(SUITE("KeepAliveFailureCallbackIsInvokedOnTimeout"))
{
LinkConfig config(true, false);
config.KeepAliveTimeout = TimeDuration::Seconds(5);
LinkLayerTest t(config);

t.link.OnLowerLayerUp();

REQUIRE(t.exe->num_pending_timers() == 1);
REQUIRE(t.listener->numKeepAliveTransmissions == 0);

REQUIRE(t.exe->advance_to_next_timer());
REQUIRE(t.exe->run_many() > 0);

REQUIRE(t.PopLastWriteAsHex() == LinkHex::RequestLinkStatus(true, 1024, 1));
REQUIRE(t.exe->num_pending_timers() == 2);
t.link.OnTxReady();
REQUIRE(t.exe->num_pending_timers() == 2);
t.exe->advance_time(config.Timeout.value);
Expand All @@ -98,7 +144,7 @@ TEST_CASE(SUITE("KeepAliveSuccessCallbackIsInvokedWhenLinkStatusReceived"))
REQUIRE(t.exe->run_many() > 0);

REQUIRE(t.PopLastWriteAsHex() == LinkHex::RequestLinkStatus(true, 1024, 1));
REQUIRE(t.exe->num_pending_timers() == 1);
REQUIRE(t.exe->num_pending_timers() == 2);
t.link.OnTxReady();
REQUIRE(t.exe->num_pending_timers() == 2);
t.OnFrame(LinkFunction::SEC_LINK_STATUS, false, false, false, 1, 1024);
Expand All @@ -123,7 +169,7 @@ TEST_CASE(SUITE("KeepAliveIsPeriodicOnFailure"))
REQUIRE(t.exe->run_many() > 0);

REQUIRE(t.PopLastWriteAsHex() == LinkHex::RequestLinkStatus(true, 1024, 1));
REQUIRE(t.exe->num_pending_timers() == 1);
REQUIRE(t.exe->num_pending_timers() == 2);
t.link.OnTxReady();
REQUIRE(t.exe->num_pending_timers() == 2);

Expand All @@ -150,10 +196,31 @@ TEST_CASE(SUITE("KeepAliveIsPeriodicOnSuccess"))
REQUIRE(t.exe->run_many() > 0);

REQUIRE(t.PopLastWriteAsHex() == LinkHex::RequestLinkStatus(true, 1024, 1));
REQUIRE(t.exe->num_pending_timers() == 1);
REQUIRE(t.exe->num_pending_timers() == 2);
t.link.OnTxReady();
REQUIRE(t.exe->num_pending_timers() == 2);
t.OnFrame(LinkFunction::SEC_LINK_STATUS, false, false, false, 1, 1024);
REQUIRE(t.listener->numKeepAliveReplys == (count + 1));
}
}

TEST_CASE(SUITE("KeepAliveSuccessCallbackIsInvokedWhenLinkStatusReceivedBeforeTransmitComplete"))
{
LinkConfig config(true, false);
config.KeepAliveTimeout = TimeDuration::Seconds(5);
LinkLayerTest t(config);

t.link.OnLowerLayerUp();

REQUIRE(t.exe->num_pending_timers() == 1);
REQUIRE(t.listener->numKeepAliveTransmissions == 0);

REQUIRE(t.exe->advance_to_next_timer());
REQUIRE(t.exe->run_many() > 0);

REQUIRE(t.PopLastWriteAsHex() == LinkHex::RequestLinkStatus(true, 1024, 1));
t.OnFrame(LinkFunction::SEC_LINK_STATUS, false, false, false, 1, 1024);
t.link.OnTxReady();
REQUIRE(t.listener->numKeepAliveReplys == 1);
REQUIRE(t.exe->num_pending_timers() == 1);
}

0 comments on commit 60b6bfd

Please sign in to comment.