Projekt

Obecné

Profil

Stáhnout (4.35 KB) Statistiky
| Větev: | Tag: | Revize:
1
#ifndef CURVEDATASERVER_H
2
#define CURVEDATASERVER_H
3

    
4
#include <QObject>
5
#include <QTcpServer>
6
#include <QTcpSocket>
7
#include <map>
8
#include <mutex>
9
#include <thread>
10

    
11

    
12
/**
13
 * Manages communication with clients who can connect to the server in order to receive real-time data about the current
14
 * exercise. The served data may be used e.g. for external visualization. A reference implementation of such a client is
15
 * the deltarobot-vr Unity application.
16
 */
17
class CurveDataServer : QObject
18
{
19
    Q_OBJECT
20

    
21
public:
22

    
23
    /**
24
     * Holds information about a client, its Qt socket, data buffer etc.
25
     */
26
    struct Client {
27
        /**
28
         * Size of the client buffer.
29
         *
30
         * @note Current implementation truncates any variable-length messages longer than what would fit in the buffer.
31
         */
32
        static const size_t BUF_SIZE = 4096;
33

    
34
        static const size_t MESSAGE_ID_SIZE = sizeof(uint16_t);      ///< Size of the protocol message identifier
35
        static const size_t MESSAGE_LENGTH_SIZE = sizeof(uint32_t);  ///< Size of the variable-length message's content length
36

    
37
        QTcpSocket* socket;                 ///< Communication socket
38
        std::map<uint64_t, uint64_t> ping;  ///< Key: ping ID;  Value: ping timestamp (msec);
39
        uint64_t latency;                   ///< Current latency
40
        uint64_t lastPong;                  ///< Timestamp of the last pong
41

    
42
        char buf[BUF_SIZE];                 ///< Message buffer
43
        size_t bufUsed = 0;                 ///< Number of bytes used up in the message buffer
44

    
45
        bool magic = false;                 ///< Whether the client has sent the correct protocol magic
46
        bool version = false;               ///< Whether the client has sent the correct protocol version
47
        bool protocolValid = false;         ///< Whether the client has sent both the correct protocol magic and version.
48

    
49
        bool initialized = false;           ///< Whether the server has initialized this client with the current curve
50

    
51
        Client(QTcpSocket* socket);
52
    };
53

    
54
    explicit CurveDataServer(quint16 port = 4242);
55
    ~CurveDataServer();
56

    
57
    /** Sends the current actuator position. */
58
    void sendActuatorPosition(float x, float y, float z);
59

    
60
    /** Sends the actual direction the actuator is moving in. */
61
    void sendActualDirection(float x, float y, float z);
62

    
63
    /** Sends the direction the actuator *should* be moving in, in order to draw the curve. */
64
    void sendTargetDirection(float x, float y, float z);
65

    
66
    /** Stores and sends the specified curve. */
67
    void sendNewCurve(QList<QVector4D> &points);
68

    
69
    /** Stores and sends the specified curve. */
70
    void sendNewCurve(QList<QVector3D> &points);
71

    
72
    /** Sends the currently stored curve. This is used for newly connected clients. */
73
    void sendCurve(Client &client);
74

    
75
    /** Sends ping messages to the clients, checks whether any clients have timed out, and disconnects any that have. */
76
    void processPings();
77

    
78
public slots:
79
    void onNewConnection();
80
    void onSocketStateChanged(QAbstractSocket::SocketState socketState);
81
    void onReadyRead();
82

    
83
private:
84
    /** Gets the client that is connected via the specified socket. */
85
    QList<Client>::iterator clientOf(QTcpSocket *socket);
86

    
87
    void handleMessage(Client& client, uint16_t messageId, void* content, size_t contentSize);
88
    void handleProtocolMagic(Client& client, char* content);
89
    void handleVersion(Client& client, uint8_t content);
90
    void handlePong(Client& client, uint64_t* content);
91
    void handleEOT(Client& client, char* content, size_t contentSize);
92

    
93
    /**
94
     * Checks whether the specified client has already sent both its protocol magic and version. If so, the appropriate
95
     * flag is set and a log is written out into qDebug.
96
     */
97
    void validateProtocol(Client& client);
98

    
99
    void removeSocket(QTcpSocket *socket);
100
    void terminateConnection(Client& client, std::string&& reason);
101
    void sendPing(Client& client);
102

    
103
    void sendPreamble(QTcpSocket *socket);
104
    void sendProtocolMagic(QTcpSocket *socket);
105
    void sendVersion(QTcpSocket *socket);
106
    void sendEot(QTcpSocket *socket, std::string&& message);
107

    
108
    void sendMessageToAllConnected(QByteArray &message);
109

    
110
    QTcpServer _server;
111

    
112
    std::recursive_mutex _socketsLock;
113
    QList<Client> _sockets;
114

    
115
    std::recursive_mutex _currentCurveLock;
116
    QList<QVector3D> _currentCurve;
117
};
118

    
119
#endif // CURVEDATASERVER_H
(3-3/19)