Overte C++ Documentation
ReceivedMessage.h
1 //
2 // ReceivedMessage.h
3 // libraries/networking/src
4 //
5 // Created by Ryan Huffman on 2015/09/15
6 // Copyright 2015 High Fidelity, Inc.
7 // Copyright 2021 Vircadia contributors.
8 //
9 // Distributed under the Apache License, Version 2.0.
10 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
11 //
12 
13 #ifndef hifi_ReceivedMessage_h
14 #define hifi_ReceivedMessage_h
15 
16 #include <QByteArray>
17 #include <QObject>
18 #include <QtCore/QSharedPointer>
19 
20 #include <atomic>
21 
22 #include "NLPacketList.h"
23 
24 class ReceivedMessage : public QObject {
25  Q_OBJECT
26 public:
27  ReceivedMessage(const NLPacketList& packetList);
28  ReceivedMessage(NLPacket& packet);
29  ReceivedMessage(QByteArray byteArray, PacketType packetType, PacketVersion packetVersion,
30  const SockAddr& senderSockAddr, NLPacket::LocalID sourceID = NLPacket::NULL_LOCAL_ID);
31 
32  QByteArray getMessage() const { return _data; }
33  const char* getRawMessage() const { return _data.constData(); }
34 
35  PacketType getType() const { return _packetType; }
36  PacketVersion getVersion() const { return _packetVersion; }
37 
38  void setFailed();
39 
40  void appendPacket(NLPacket& packet);
41 
42  bool failed() const { return _failed; }
43  bool isComplete() const { return _isComplete; }
44 
45  NLPacket::LocalID getSourceID() const { return _sourceID; }
46  const SockAddr& getSenderSockAddr() { return _senderSockAddr; }
47 
48  qint64 getPosition() const { return _position; }
49 
50  // Get the number of packets that were used to send this message
51  qint64 getNumPackets() const { return _numPackets; }
52 
53  qint64 getFirstPacketReceiveTime() const { return _firstPacketReceiveTime; }
54 
55  qint64 getSize() const { return _data.size(); }
56 
57  qint64 getBytesLeftToRead() const { return _data.size() - _position; }
58 
59  void seek(qint64 position) { _position = position; }
60 
61  qint64 peek(char* data, qint64 size);
62  qint64 read(char* data, qint64 size);
63 
64  // Temporary functionality for reading in the first HEAD_DATA_SIZE bytes of the message
65  // safely across threads.
66  qint64 readHead(char* data, qint64 size);
67 
68  QByteArray peek(qint64 size);
69  QByteArray read(qint64 size);
70  QByteArray readAll();
71 
72  QString readString();
73 
74  QByteArray readHead(qint64 size);
75 
76  // This will return a QByteArray referencing the underlying data _without_ refcounting that data.
77  // Be careful when using this method, only use it when the lifetime of the returned QByteArray will not
78  // exceed that of the ReceivedMessage.
79  QByteArray readWithoutCopy(qint64 size);
80 
81  template<typename T> qint64 peekPrimitive(T* data);
82  template<typename T> qint64 readPrimitive(T* data);
83 
84  template<typename T> qint64 readHeadPrimitive(T* data);
85 
86 signals:
87  void progress(qint64 size);
88  void completed();
89 
90 private slots:
91  void onComplete();
92 
93 private:
94  QByteArray _data;
95  QByteArray _headData;
96 
97  std::atomic<qint64> _position { 0 };
98  std::atomic<qint64> _numPackets { 0 };
99  std::atomic<quint64> _firstPacketReceiveTime { 0 };
100 
101  NLPacket::LocalID _sourceID { NLPacket::NULL_LOCAL_ID };
102  PacketType _packetType;
103  PacketVersion _packetVersion;
104  SockAddr _senderSockAddr;
105 
106  std::atomic<bool> _isComplete { true };
107  std::atomic<bool> _failed { false };
108 };
109 
110 Q_DECLARE_METATYPE(ReceivedMessage*)
111 Q_DECLARE_METATYPE(QSharedPointer<ReceivedMessage>)
112 
113 template<typename T> qint64 ReceivedMessage::peekPrimitive(T* data) {
114  return peek(reinterpret_cast<char*>(data), sizeof(T));
115 }
116 
117 template<typename T> qint64 ReceivedMessage::readPrimitive(T* data) {
118  return read(reinterpret_cast<char*>(data), sizeof(T));
119 }
120 
121 template<typename T> qint64 ReceivedMessage::readHeadPrimitive(T* data) {
122  return readHead(reinterpret_cast<char*>(data), sizeof(T));
123 }
124 
125 #endif