-
Notifications
You must be signed in to change notification settings - Fork 0
/
dsconvoprotocol.cpp
152 lines (127 loc) · 4.25 KB
/
dsconvoprotocol.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include "dsconvoprotocol.h"
#include <QRegularExpression>
#include <QTextStream>
#define PARSE_PAYLOAD(klass, from, into, fallback) \
do { \
klass *payload = new klass(); \
if (payload->ParseFromString((from))) { \
(into) = payload; \
} else { \
(into) = (fallback); \
} \
} while (0);
namespace {
using DSConvoMessage = DSConvoProtocol::DSConvoMessage;
inline QByteArray makeMessage(DSConvoMessage::MessageType,
const google::protobuf::Message&);
inline QByteArray makeMessage(DSConvoMessage::MessageType);
} // anonymous
namespace DSConvo {
namespace Protocol {
bool parseMessage(std::istream *is, ParsedMessage &into)
{
using namespace DSConvoProtocol;
DSConvoMessage message;
if (!message.ParseFromIstream(is)) {
qDebug("[DEBUG] [DSConvo::Protocol::parseMessage()] bad message");
return false;
}
DSConvoMessage::MessageType type = message.type();
const std::string &data = message.payload();
google::protobuf::Message *ptr = nullptr;
switch (type) {
case DSConvoMessage::HELLO_REQUEST:
PARSE_PAYLOAD(HelloRequestPayload, data, ptr, INVALID_PAYLOAD);
break;
case DSConvoMessage::HELLO_REPLY:
PARSE_PAYLOAD(HelloReplyPayload, data, ptr, INVALID_PAYLOAD);
break;
case DSConvoMessage::MESSAGE_REQUEST:
PARSE_PAYLOAD(MessageRequestPayload, data, ptr, INVALID_PAYLOAD);
break;
case DSConvoMessage::MESSAGE_BROADCAST:
PARSE_PAYLOAD(MessageBroadcastPayload, data, ptr, INVALID_PAYLOAD);
break;
default:
// unreachable?
return false;
}
if (ptr == INVALID_PAYLOAD) {
return false;
}
into.first = type;
into.second = ptr;
return true;
}
QByteArray makeHelloRequest(const std::string &username)
{
DSConvoProtocol::HelloRequestPayload payload;
payload.set_username(username);
return makeMessage(DSConvoMessage::HELLO_REQUEST, payload);
}
QByteArray makeHelloReply(DSConvoProtocol::HelloReplyPayload::HelloReplyError result,
const std::string &username)
{
Q_ASSERT(result != DSConvoProtocol::HelloReplyPayload::INVALID);
DSConvoProtocol::HelloReplyPayload payload;
payload.set_result(result);
payload.set_username(username);
return makeMessage(DSConvoMessage::HELLO_REPLY, payload);
}
QByteArray makeMessageRequest(const std::string &msg)
{
DSConvoProtocol::MessageRequestPayload payload;
payload.set_msg(msg);
return makeMessage(DSConvoMessage::MESSAGE_REQUEST, payload);
}
QByteArray makeMessageBroadcast(const std::string &username,
const std::string &displayName,
const std::string &msg)
{
DSConvoProtocol::MessageBroadcastPayload payload;
payload.set_username(username);
payload.set_display_name(displayName);
payload.set_msg(msg);
return makeMessage(DSConvoMessage::MESSAGE_BROADCAST, payload);
}
QByteArray makeGoodbye()
{
return makeMessage(DSConvoMessage::GOODBYE);
}
} // namespace DSConvo::Protocol
QString formatMessage(const Protocol::MessageBroadcast &m)
{
static QRegularExpression const lineBreakGroupPattern("[\r\n]{2,}");
QString text = m.message;
text.replace(lineBreakGroupPattern, "\n");
text.prepend(" ");
text.replace("\n", "\n ");
QString out;
QTextStream(&out) << m.displayName << " >\n" << text << "\n";
return out;
}
} // namespace DSConvo
namespace {
inline QByteArray makeMessage(DSConvoMessage::MessageType type,
const google::protobuf::Message &payload)
{
Q_ASSERT(type != DSConvoMessage::INVALID);
DSConvoMessage message;
std::string payloadBytes;
std::string rawMessage;
payload.SerializeToString(&payloadBytes);
message.set_type(type);
message.set_payload(payloadBytes);
message.SerializeToString(&rawMessage);
return QByteArray::fromStdString(rawMessage);
}
inline QByteArray makeMessage(DSConvoMessage::MessageType type)
{
Q_ASSERT(type != DSConvoMessage::INVALID);
DSConvoMessage message;
std::string rawMessage;
message.set_type(type);
message.SerializeToString(&rawMessage);
return QByteArray::fromStdString(rawMessage);
}
} // anonymous