Projekt

Obecné

Profil

Stáhnout (11.3 KB) Statistiky
| Větev: | Tag: | Revize:
1
#include "curvedataserver.h"
2

    
3
#include <QDebug>
4
#include <QHostAddress>
5
#include <QAbstractSocket>
6
#include <QVector4D>
7
#include <chrono>
8

    
9

    
10
// Utility functions ///////////////////////////////////////////////////////////////////////////////////////////////////
11

    
12
static QByteArray message8(uint16_t messageId, uint8_t content = 0) {
13
    QByteArray result(2 + 1, 0);
14
    result[0] = ((uint8_t*) &messageId)[0];
15
    result[1] = ((uint8_t*) &messageId)[1];
16
    result[2] = content;
17
    return result;
18
}
19

    
20
static QByteArray message16(uint16_t messageId, uint16_t content = 0) {
21
    QByteArray result(2 + 2, 0);
22
    result[0] = ((uint8_t*) &messageId)[0];
23
    result[1] = ((uint8_t*) &messageId)[1];
24
    result[2] = ((uint8_t*) &content)[0];
25
    result[3] = ((uint8_t*) &content)[1];
26
    return result;
27
}
28

    
29
static QByteArray message32(uint16_t messageId, uint32_t content = 0) {
30
    QByteArray result(2 + 4, 0);
31
    result[0] = ((uint8_t*) &messageId)[0];
32
    result[1] = ((uint8_t*) &messageId)[1];
33
    result[2] = ((uint8_t*) &content)[0];
34
    result[3] = ((uint8_t*) &content)[1];
35
    result[4] = ((uint8_t*) &content)[2];
36
    result[5] = ((uint8_t*) &content)[3];
37
    return result;
38
}
39

    
40
static QByteArray message64(uint16_t messageId, uint64_t content = 0) {
41
    QByteArray result(2 + 8, 0);
42
    result[0] = ((uint8_t*) &messageId)[0];
43
    result[1] = ((uint8_t*) &messageId)[1];
44
    result[2] = ((uint8_t*) &content)[0];
45
    result[3] = ((uint8_t*) &content)[1];
46
    result[4] = ((uint8_t*) &content)[2];
47
    result[5] = ((uint8_t*) &content)[3];
48
    result[6] = ((uint8_t*) &content)[4];
49
    result[7] = ((uint8_t*) &content)[5];
50
    result[8] = ((uint8_t*) &content)[6];
51
    result[9] = ((uint8_t*) &content)[7];
52
    return result;
53
}
54

    
55
static QByteArray message128(uint16_t messageId,
56
                             uint32_t contentX = 0,
57
                             uint32_t contentY = 0,
58
                             uint32_t contentZ = 0,
59
                             uint32_t contentW = 0)
60
{
61
    QByteArray result(2 + 16, 0);
62
    result[0] = ((uint8_t*) &messageId)[0];
63
    result[1] = ((uint8_t*) &messageId)[1];
64

    
65
    result[2] = ((uint8_t*) &contentX)[0];
66
    result[3] = ((uint8_t*) &contentX)[1];
67
    result[4] = ((uint8_t*) &contentX)[2];
68
    result[5] = ((uint8_t*) &contentX)[3];
69

    
70
    result[6] = ((uint8_t*) &contentY)[0];
71
    result[7] = ((uint8_t*) &contentY)[1];
72
    result[8] = ((uint8_t*) &contentY)[2];
73
    result[9] = ((uint8_t*) &contentY)[3];
74

    
75
    result[10] = ((uint8_t*) &contentZ)[0];
76
    result[11] = ((uint8_t*) &contentZ)[1];
77
    result[12] = ((uint8_t*) &contentZ)[2];
78
    result[13] = ((uint8_t*) &contentZ)[3];
79

    
80
    result[14] = ((uint8_t*) &contentW)[0];
81
    result[15] = ((uint8_t*) &contentW)[1];
82
    result[16] = ((uint8_t*) &contentW)[2];
83
    result[17] = ((uint8_t*) &contentW)[3];
84
    return result;
85
}
86

    
87
static QByteArray messageVarLength(uint16_t messageId, uint32_t length, const char* content = nullptr) {
88
    QByteArray result(2 + 4 + length, 0);
89
    result[0] = ((uint8_t*) &messageId)[0];
90
    result[1] = ((uint8_t*) &messageId)[1];
91
    result[2] = ((uint8_t*) &length)[0];
92
    result[3] = ((uint8_t*) &length)[1];
93
    result[4] = ((uint8_t*) &length)[2];
94
    result[5] = ((uint8_t*) &length)[3];
95

    
96
    if (content) {
97
        for (uint32_t i = 0; i < length; i++) {
98
            result[6 + i] = content[i];
99
        }
100
    }
101
    return result;
102
}
103

    
104
inline long currentTimeMillis() {
105
    return std::chrono::duration_cast<std::chrono::milliseconds>(
106
                std::chrono::steady_clock::now().time_since_epoch())
107
            .count();
108
}
109

    
110

    
111
// Client //////////////////////////////////////////////////////////////////////////////////////////////////////////////
112

    
113
CurveDataServer::Client::Client(QTcpSocket* socket) :
114
    socket(socket),
115
    lastPong(currentTimeMillis()),
116
    bufUsed(0)
117
{}
118

    
119

    
120
// Server //////////////////////////////////////////////////////////////////////////////////////////////////////////////
121

    
122
CurveDataServer::CurveDataServer() :
123
    _server(this),
124
    _sockets()
125
{
126
    _server.listen(QHostAddress::Any, 4242);
127
    connect(&_server, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
128
}
129

    
130
CurveDataServer::~CurveDataServer()
131
{
132
    std::lock_guard<decltype (_socketsLock)> l(_socketsLock);
133
    for (auto& client : _sockets)
134
    {
135
        sendEot(client.socket, "Server is stopping");
136
        client.socket->close();
137
    }
138
    _sockets.clear();
139
}
140

    
141
void CurveDataServer::onNewConnection()
142
{
143
    QTcpSocket *clientSocket = _server.nextPendingConnection();
144
    connect(clientSocket, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
145
    connect(clientSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(onSocketStateChanged(QAbstractSocket::SocketState)));
146

    
147
    sendPreamble(clientSocket);
148
    _sockets.push_back(Client(clientSocket));
149
}
150

    
151
void CurveDataServer::onSocketStateChanged(QAbstractSocket::SocketState socketState)
152
{
153
    if (socketState == QAbstractSocket::UnconnectedState)
154
    {
155
        QTcpSocket* sender = static_cast<QTcpSocket*>(QObject::sender());
156

    
157
        std::lock_guard<decltype (_socketsLock)> l(_socketsLock);
158
        for (auto it = _sockets.begin(); it != _sockets.end(); it++) {
159
            if (it->socket == sender) {
160
                _sockets.erase(it);
161
                break;
162
            }
163
        }
164
    }
165
}
166

    
167
void CurveDataServer::onReadyRead()
168
{
169
    std::lock_guard<decltype (_socketsLock)> l(_socketsLock);
170

    
171
    QTcpSocket* sender = static_cast<QTcpSocket*>(QObject::sender());
172
    auto it = clientOf(sender);
173
    if (it == _sockets.end()) {
174
        return;
175
    }
176
    Client& client = *it;
177

    
178
    while (sender->bytesAvailable()) {
179
        if (client.bufUsed < Client::MESSAGE_ID_SIZE) {
180
            qint64 toRead = qMin(qint64(Client::MESSAGE_ID_SIZE - client.bufUsed), sender->bytesAvailable());
181
            client.bufUsed += sender->read(&client.buf[client.bufUsed], toRead);
182
        }
183

    
184
        if (client.bufUsed < 2) {
185
            // no ID yet, wait for more data
186
            return;
187
        }
188

    
189
        uint16_t messageId = *((uint16_t*) client.buf);
190
        qint64 contentSize;
191
        switch (messageId & 0xF000) {
192
        case 0x0000:
193
            contentSize = 1;
194
            break;
195
        case 0x1000:
196
            contentSize = 2;
197
            break;
198
        case 0x2000:
199
            contentSize = 4;
200
            break;
201
        case 0x3000:
202
            contentSize = 8;
203
            break;
204
        case 0x4000:
205
            contentSize = 16;
206
            break;
207
        case 0xF000:
208
            // TODO - implement support for variable length messages
209
            return;
210
        default:
211
            // unsupported message size
212
            return;
213
        }
214

    
215
        qint64 toRead = qMin(qint64(contentSize - (client.bufUsed - Client::MESSAGE_ID_SIZE)), sender->bytesAvailable());
216
        if (toRead > 0) {
217
            client.bufUsed += sender->read(&client.buf[client.bufUsed], toRead);
218
        }
219

    
220
        if (client.bufUsed == (Client::MESSAGE_ID_SIZE + contentSize)) {
221
            handleMessage(client, messageId, &client.buf[Client::MESSAGE_ID_SIZE]);
222
            client.bufUsed = 0;
223
        }
224
    }
225
}
226

    
227
void CurveDataServer::handleMessage(Client& client, uint16_t messageId, void *content) {
228
    switch (messageId) {
229
    case 0x3001:
230
        qDebug() << "Magic arrived!";
231
        break;
232
    case 0x2002:
233
        qDebug() << "Version arrived!";
234
        break;
235
    case 0x3005:
236
        qDebug() << "Pong " << *((uint64_t*) content) << " arrived!";
237
        break;
238
    }
239
}
240

    
241
void CurveDataServer::sendActuatorPosition(float x, float y, float z)
242
{
243
    QByteArray message = message128(0x4003,
244
                                    *((uint32_t*) &x),
245
                                    *((uint32_t*) &y),
246
                                    *((uint32_t*) &z));
247

    
248
    {
249
        std::lock_guard<decltype (_socketsLock)> l(_socketsLock);
250
        for (auto& client : _sockets) {
251
                client.socket->write(message);
252
        }
253
    }
254
}
255

    
256
void CurveDataServer::sendActualDirection(float x, float y, float z)
257
{
258
    QByteArray message = message128(0x4007,
259
                                    *((uint32_t*) &x),
260
                                    *((uint32_t*) &y),
261
                                    *((uint32_t*) &z));
262

    
263
    {
264
        std::lock_guard<decltype (_socketsLock)> l(_socketsLock);
265
        for (auto& client : _sockets) {
266
                client.socket->write(message);
267
        }
268
    }
269
}
270

    
271
void CurveDataServer::sendTargetDirection(float x, float y, float z)
272
{
273
    QByteArray message = message128(0x4008,
274
                                    *((uint32_t*) &x),
275
                                    *((uint32_t*) &y),
276
                                    *((uint32_t*) &z));
277

    
278
    {
279
        std::lock_guard<decltype (_socketsLock)> l(_socketsLock);
280
        for (auto& client : _sockets) {
281
                client.socket->write(message);
282
        }
283
    }
284
}
285

    
286
void CurveDataServer::sendNewCurve(QList<QVector3D> points)
287
{
288
    int size = points.size();
289

    
290
    QByteArray message = messageVarLength(0xF009, (uint32_t) size * 12);
291

    
292
    for (int i = 0; i < size; i++)
293
    {
294
        float xf = points[i].x();
295
        float yf = points[i].y();
296
        float zf = points[i].z();
297

    
298
        uint8_t *x = ((uint8_t*) &xf);
299
        uint8_t *y = ((uint8_t*) &yf);
300
        uint8_t *z = ((uint8_t*) &zf);
301

    
302
        message[2 + 4 + i*12 + 0] = x[0];
303
        message[2 + 4 + i*12 + 1] = x[1];
304
        message[2 + 4 + i*12 + 2] = x[2];
305
        message[2 + 4 + i*12 + 3] = x[3];
306

    
307
        message[2 + 4 + i*12 + 4] = y[0];
308
        message[2 + 4 + i*12 + 5] = y[1];
309
        message[2 + 4 + i*12 + 6] = y[2];
310
        message[2 + 4 + i*12 + 7] = y[3];
311

    
312
        message[2 + 4 + i*12 + 8] = z[0];
313
        message[2 + 4 + i*12 + 9] = z[1];
314
        message[2 + 4 + i*12 + 10] = z[2];
315
        message[2 + 4 + i*12 + 11] = z[3];
316
    }
317

    
318
    {
319
        std::lock_guard<decltype (_socketsLock)> l(_socketsLock);
320
        for (auto& client : _sockets) {
321
                client.socket->write(message);
322
        }
323
    }
324
}
325

    
326
void CurveDataServer::sendNewCurve(QList<QVector4D> points)
327
{
328
    QList<QVector3D> curve3d;
329
    int itemCount = points.size();
330

    
331
    curve3d.clear();
332
    if (itemCount > MAX_CURVE_SIZE)
333
        itemCount = MAX_CURVE_SIZE;
334
    for (int i = 0; i < itemCount; i++)
335
    {
336
        curve3d.append(points[i].toVector3D());
337
    }
338

    
339
    sendNewCurve(curve3d);
340
}
341

    
342
QList<CurveDataServer::Client>::iterator CurveDataServer::clientOf(QTcpSocket *socket) {
343
    std::lock_guard<decltype (_socketsLock)> l(_socketsLock);
344
    for (auto it = _sockets.begin(); it != _sockets.end(); it++) {
345
        if (it->socket == socket) {
346
            return it;
347
        }
348
    }
349
    return _sockets.end();
350
}
351

    
352
void CurveDataServer::sendPreamble(QTcpSocket *socket)
353
{
354
    sendProtocolMagic(socket);
355
    sendVersion(socket);
356
}
357

    
358
void CurveDataServer::sendProtocolMagic(QTcpSocket *socket)
359
{
360
    char *messageContent = "DeltaRVr";
361
    QByteArray message = message64(0x3001, *((uint64_t*) messageContent));
362

    
363
    socket->write(message);
364

    
365
    qDebug() << "Sent Protocol Magic to" << socket->peerAddress();
366
    //qDebug() << message.toHex();
367
}
368

    
369
void CurveDataServer::sendVersion(QTcpSocket *socket)
370
{
371
    QByteArray message = message32(0x2002, 1);
372

    
373
    socket->write(message);
374

    
375
    qDebug() << "Sent Protocol Version to" << socket->peerAddress();
376
    //qDebug() << message.toHex();
377
}
378

    
379
void CurveDataServer::sendEot(QTcpSocket *socket, std::string&& reason)
380
{
381
    QByteArray message = messageVarLength(0xF006, ((uint32_t) reason.length()), reason.c_str());
382
    socket->write(message);
383
}
(2-2/19)