-
Notifications
You must be signed in to change notification settings - Fork 0
/
dsconvostream.cpp
102 lines (86 loc) · 2.64 KB
/
dsconvostream.cpp
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
#include "dsconvostream.h"
#define IO_OPENMODE (std::ios_base::binary | \
std::ios_base::in | \
std::ios_base::out)
DSConvoStream::DSConvoStream(QObject *parent)
: QObject(parent)
, buffer(new QByteArray)
, bufferOffset(0)
, chunkOffset(0)
, state(Length)
, io(IO_OPENMODE)
{
buffer->resize(BUFFER_SIZE);
}
void DSConvoStream::handleRecvData(const QByteArray &data)
{
static constexpr int LENGTH_CHUNK_SIZE = sizeof(quint16);
int dataOffset = 0;
int dataSize = data.size();
while (dataOffset < dataSize) {
int chunkSize;
switch (state) {
case Length:
chunkSize = LENGTH_CHUNK_SIZE;
break;
case Message:
chunkSize = stateArg;
break;
}
int numBytes = qMin(dataSize - dataOffset, chunkSize - chunkOffset);
numBytes = qMin(numBytes, BUFFER_SIZE - bufferOffset);
buffer->replace(bufferOffset, numBytes, data.mid(dataOffset, numBytes));
dataOffset += numBytes;
chunkOffset += numBytes;
bufferOffset += numBytes;
if (chunkOffset == chunkSize || bufferOffset == BUFFER_SIZE) {
handleBufferData(chunkSize);
}
}
}
void DSConvoStream::handleBufferData(int chunkSize)
{
if (chunkSize < BUFFER_SIZE) {
Q_ASSERT(bufferOffset == chunkSize && chunkOffset == chunkSize);
}
switch (state) {
case Length:
stateArg = *reinterpret_cast<const quint32*>(buffer->constData()) & 0xffff;
qDebug("[DEBUG] DSConvoStream::handleBufferData(%d) "
"(state = Length ; stateArg = %d)", chunkSize, stateArg);
if (stateArg > 0) {
state = Message;
io.str(std::string());
io.clear();
} else {
qDebug("[DEBUG] [DSConvoStream Length] ignoring empty message");
}
break;
case Message:
qDebug("[DEBUG] DSConvoStream::handleBufferData(%d) "
"(state = Message ; chunkOffset = %d)", chunkSize, chunkOffset);
io.write(buffer->constData(), bufferOffset);
if (chunkOffset == chunkSize) {
qDebug("[DEBUG] [DSConvoStream Message] message received");
handleMessage();
state = Length;
}
break;
}
if (chunkOffset == chunkSize) {
bufferOffset = 0;
chunkOffset = 0;
} else if (bufferOffset == BUFFER_SIZE) {
bufferOffset = 0;
}
}
bool DSConvoStream::handleMessage()
{
using namespace DSConvo::Protocol;
ParsedMessage message;
if (!parseMessage(&io, message)) {
return false;
}
emit messageParsed(message);
return true;
}