1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
#include <phosphor-logging/log.hpp>
#include "main.hpp"
#include "sd_event_loop.hpp"
#include "sol_context.hpp"
#include "sol_manager.hpp"
namespace sol
{
using namespace phosphor::logging;
void Context::processInboundPayload(uint8_t seqNum,
uint8_t ackSeqNum,
uint8_t count,
bool status,
const Buffer& input)
{
uint8_t respAckSeqNum = 0;
uint8_t acceptedCount = 0;
auto ack = false;
/*
* Check if the Inbound sequence number is same as the expected one.
* If the Packet Sequence Number is 0, it is an ACK-Only packet. Multiple
* outstanding sequence numbers are not supported in this version of the SOL
* specification. Retried packets use the same sequence number as the first
* packet.
*/
if(seqNum && (seqNum != seqNums.get(true)))
{
log<level::INFO>("Out of sequence SOL packet - packet is dropped");
return;
}
/*
* Check if the expected ACK/NACK sequence number is same as the
* ACK/NACK sequence number in the packet. If packet ACK/NACK sequence
* number is 0, then it is an informational packet. No request packet being
* ACK'd or NACK'd.
*/
if (ackSeqNum && (ackSeqNum != seqNums.get(false)))
{
log<level::INFO>("Out of sequence ack number - SOL packet is dropped");
return;
}
/*
* Retry the SOL payload packet in the following conditions:
*
* a) NACK in Operation/Status
* b) Accepted Character Count does not match with the sent out SOL payload
* c) Non-zero Packet ACK/NACK Sequence Number
*/
if (status || ((count != expectedCharCount) && ackSeqNum))
{
resendPayload(noClear);
std::get<eventloop::EventLoop&>(singletonPool).switchTimer
(payloadInstance, eventloop::Timers::RETRY, false);
std::get<eventloop::EventLoop&>(singletonPool).switchTimer
(payloadInstance, eventloop::Timers::RETRY, true);
return;
}
/*
* Clear the sent data once the acknowledgment sequence number matches
* and the expected character count matches.
*/
else if ((count == expectedCharCount) && ackSeqNum)
{
// Clear the Host Console Buffer
std::get<sol::Manager&>(singletonPool).dataBuffer.erase(count);
// Once it is acknowledged stop the retry interval timer
std::get<eventloop::EventLoop&>(singletonPool).switchTimer(
payloadInstance, eventloop::Timers::RETRY, false);
retryCounter = maxRetryCount;
expectedCharCount = 0;
payloadCache.clear();
}
// Write character data to the Host Console
if (!input.empty() && seqNum)
{
auto rc = std::get<sol::Manager&>(singletonPool).writeConsoleSocket(
input);
if (rc)
{
log<level::ERR>("Writing to console socket descriptor failed");
ack = true;
}
else
{
respAckSeqNum = seqNum;
ack = false;
acceptedCount = input.size();
}
}
if (seqNum != 0)
{
seqNums.incInboundSeqNum();
prepareResponse(respAckSeqNum, acceptedCount, ack);
}
else
{
std::get<eventloop::EventLoop&>(singletonPool).switchTimer
(payloadInstance, eventloop::Timers::ACCUMULATE, true);
}
}
void Context::prepareResponse(uint8_t ackSeqNum,
uint8_t count,
bool ack)
{
}
void Context::resendPayload(bool clear)
{
}
} // namespace sol
|