mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 02:52:57 +02:00
Make NodeJSONStats reliable
This commit is contained in:
parent
c4c6e7264e
commit
5808658958
24 changed files with 130 additions and 109 deletions
|
@ -12,7 +12,6 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#include <AddressManager.h>
|
#include <AddressManager.h>
|
||||||
#include <JSONBreakableMarshal.h>
|
|
||||||
#include <LogHandler.h>
|
#include <LogHandler.h>
|
||||||
#include <udt/PacketHeaders.h>
|
#include <udt/PacketHeaders.h>
|
||||||
|
|
||||||
|
|
|
@ -12,14 +12,12 @@
|
||||||
|
|
||||||
#include "AssetServer.h"
|
#include "AssetServer.h"
|
||||||
|
|
||||||
#include <QBuffer>
|
#include <QCoreApplication>
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
|
#include <QDateTime>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QEventLoop>
|
|
||||||
#include <QRunnable>
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#include "NetworkLogging.h"
|
#include "NetworkLogging.h"
|
||||||
|
|
|
@ -52,7 +52,7 @@ void SendAssetTask::run() {
|
||||||
qDebug() << "Received a request for the file (" << messageID << "): " << hexHash << " from " << start << " to " << end;
|
qDebug() << "Received a request for the file (" << messageID << "): " << hexHash << " from " << start << " to " << end;
|
||||||
|
|
||||||
qDebug() << "Starting task to send asset: " << hexHash << " for messageID " << messageID;
|
qDebug() << "Starting task to send asset: " << hexHash << " for messageID " << messageID;
|
||||||
auto replyPacketList = std::unique_ptr<NLPacketList>(new NLPacketList(PacketType::AssetGetReply, QByteArray(), true, true));
|
auto replyPacketList = NLPacketList::create(PacketType::AssetGetReply, QByteArray(), true, true);
|
||||||
|
|
||||||
replyPacketList->write(assetHash);
|
replyPacketList->write(assetHash);
|
||||||
|
|
||||||
|
|
|
@ -219,7 +219,7 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup a PacketList for the avatarPackets
|
// setup a PacketList for the avatarPackets
|
||||||
NLPacketList avatarPacketList(PacketType::BulkAvatarData);
|
auto avatarPacketList = NLPacketList::create(PacketType::BulkAvatarData);
|
||||||
|
|
||||||
// this is an AGENT we have received head data from
|
// this is an AGENT we have received head data from
|
||||||
// send back a packet with other active node data to this node
|
// send back a packet with other active node data to this node
|
||||||
|
@ -292,13 +292,13 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
otherNodeData->getLastReceivedSequenceNumber());
|
otherNodeData->getLastReceivedSequenceNumber());
|
||||||
|
|
||||||
// start a new segment in the PacketList for this avatar
|
// start a new segment in the PacketList for this avatar
|
||||||
avatarPacketList.startSegment();
|
avatarPacketList->startSegment();
|
||||||
|
|
||||||
numAvatarDataBytes += avatarPacketList.write(otherNode->getUUID().toRfc4122());
|
numAvatarDataBytes += avatarPacketList->write(otherNode->getUUID().toRfc4122());
|
||||||
numAvatarDataBytes +=
|
numAvatarDataBytes +=
|
||||||
avatarPacketList.write(otherAvatar.toByteArray(false, randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO));
|
avatarPacketList->write(otherAvatar.toByteArray(false, randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO));
|
||||||
|
|
||||||
avatarPacketList.endSegment();
|
avatarPacketList->endSegment();
|
||||||
|
|
||||||
// if the receiving avatar has just connected make sure we send out the mesh and billboard
|
// if the receiving avatar has just connected make sure we send out the mesh and billboard
|
||||||
// for this avatar (assuming they exist)
|
// for this avatar (assuming they exist)
|
||||||
|
@ -344,10 +344,10 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
});
|
});
|
||||||
|
|
||||||
// close the current packet so that we're always sending something
|
// close the current packet so that we're always sending something
|
||||||
avatarPacketList.closeCurrentPacket(true);
|
avatarPacketList->closeCurrentPacket(true);
|
||||||
|
|
||||||
// send the avatar data PacketList
|
// send the avatar data PacketList
|
||||||
nodeList->sendPacketList(avatarPacketList, *node);
|
nodeList->sendPacketList(std::move(avatarPacketList), *node);
|
||||||
|
|
||||||
// record the bytes sent for other avatar data in the AvatarMixerClientData
|
// record the bytes sent for other avatar data in the AvatarMixerClientData
|
||||||
nodeData->recordSentAvatarData(numAvatarDataBytes);
|
nodeData->recordSentAvatarData(numAvatarDataBytes);
|
||||||
|
|
|
@ -238,7 +238,7 @@ int OctreeInboundPacketProcessor::sendNackPackets() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
NLPacketList nackPacketList(_myServer->getMyEditNackType());
|
auto nackPacketList = NLPacketList::create(_myServer->getMyEditNackType());
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
int packetsSent = 0;
|
int packetsSent = 0;
|
||||||
|
|
||||||
|
@ -274,18 +274,18 @@ int OctreeInboundPacketProcessor::sendNackPackets() {
|
||||||
|
|
||||||
while (it != missingSequenceNumbers.constEnd()) {
|
while (it != missingSequenceNumbers.constEnd()) {
|
||||||
unsigned short int sequenceNumber = *it;
|
unsigned short int sequenceNumber = *it;
|
||||||
nackPacketList.writePrimitive(sequenceNumber);
|
nackPacketList->writePrimitive(sequenceNumber);
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (nackPacketList.getNumPackets()) {
|
if (nackPacketList->getNumPackets()) {
|
||||||
qDebug() << "NACK Sent back to editor/client... destinationNode=" << nodeUUID;
|
qDebug() << "NACK Sent back to editor/client... destinationNode=" << nodeUUID;
|
||||||
|
|
||||||
packetsSent += nackPacketList.getNumPackets();
|
packetsSent += nackPacketList->getNumPackets();
|
||||||
|
|
||||||
// send the list of nack packets
|
// send the list of nack packets
|
||||||
nodeList->sendPacketList(nackPacketList, *destinationNode);
|
nodeList->sendPacketList(std::move(nackPacketList), *destinationNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
++i;
|
++i;
|
||||||
|
|
|
@ -287,7 +287,7 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) {
|
||||||
packetReceiver.registerListener(PacketType::RequestAssignment, this, "processRequestAssignmentPacket");
|
packetReceiver.registerListener(PacketType::RequestAssignment, this, "processRequestAssignmentPacket");
|
||||||
packetReceiver.registerListener(PacketType::DomainListRequest, this, "processListRequestPacket");
|
packetReceiver.registerListener(PacketType::DomainListRequest, this, "processListRequestPacket");
|
||||||
packetReceiver.registerListener(PacketType::DomainServerPathQuery, this, "processPathQueryPacket");
|
packetReceiver.registerListener(PacketType::DomainServerPathQuery, this, "processPathQueryPacket");
|
||||||
packetReceiver.registerListener(PacketType::NodeJsonStats, this, "processNodeJSONStatsPacket");
|
packetReceiver.registerMessageListener(PacketType::NodeJsonStats, this, "processNodeJSONStatsPacket");
|
||||||
|
|
||||||
// NodeList won't be available to the settings manager when it is created, so call registerListener here
|
// NodeList won't be available to the settings manager when it is created, so call registerListener here
|
||||||
packetReceiver.registerListener(PacketType::DomainSettingsRequest, &_settingsManager, "processSettingsRequestPacket");
|
packetReceiver.registerListener(PacketType::DomainSettingsRequest, &_settingsManager, "processSettingsRequestPacket");
|
||||||
|
@ -679,10 +679,10 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
|
||||||
extendedHeaderStream << (quint8) node->getCanAdjustLocks();
|
extendedHeaderStream << (quint8) node->getCanAdjustLocks();
|
||||||
extendedHeaderStream << (quint8) node->getCanRez();
|
extendedHeaderStream << (quint8) node->getCanRez();
|
||||||
|
|
||||||
NLPacketList domainListPackets(PacketType::DomainList, extendedHeader);
|
auto domainListPackets = NLPacketList::create(PacketType::DomainList, extendedHeader);
|
||||||
|
|
||||||
// always send the node their own UUID back
|
// always send the node their own UUID back
|
||||||
QDataStream domainListStream(&domainListPackets);
|
QDataStream domainListStream(domainListPackets.get());
|
||||||
|
|
||||||
DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(node->getLinkedData());
|
DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(node->getLinkedData());
|
||||||
|
|
||||||
|
@ -698,7 +698,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
|
||||||
if (otherNode->getUUID() != node->getUUID() && nodeInterestSet.contains(otherNode->getType())) {
|
if (otherNode->getUUID() != node->getUUID() && nodeInterestSet.contains(otherNode->getType())) {
|
||||||
|
|
||||||
// since we're about to add a node to the packet we start a segment
|
// since we're about to add a node to the packet we start a segment
|
||||||
domainListPackets.startSegment();
|
domainListPackets->startSegment();
|
||||||
|
|
||||||
// don't send avatar nodes to other avatars, that will come from avatar mixer
|
// don't send avatar nodes to other avatars, that will come from avatar mixer
|
||||||
domainListStream << *otherNode.data();
|
domainListStream << *otherNode.data();
|
||||||
|
@ -707,17 +707,17 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
|
||||||
domainListStream << connectionSecretForNodes(node, otherNode);
|
domainListStream << connectionSecretForNodes(node, otherNode);
|
||||||
|
|
||||||
// we've added the node we wanted so end the segment now
|
// we've added the node we wanted so end the segment now
|
||||||
domainListPackets.endSegment();
|
domainListPackets->endSegment();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// send an empty list to the node, in case there were no other nodes
|
// send an empty list to the node, in case there were no other nodes
|
||||||
domainListPackets.closeCurrentPacket(true);
|
domainListPackets->closeCurrentPacket(true);
|
||||||
|
|
||||||
// write the PacketList to this node
|
// write the PacketList to this node
|
||||||
limitedNodeList->sendPacketList(domainListPackets, *node);
|
limitedNodeList->sendPacketList(std::move(domainListPackets), *node);
|
||||||
}
|
}
|
||||||
|
|
||||||
QUuid DomainServer::connectionSecretForNodes(const SharedNodePointer& nodeA, const SharedNodePointer& nodeB) {
|
QUuid DomainServer::connectionSecretForNodes(const SharedNodePointer& nodeA, const SharedNodePointer& nodeB) {
|
||||||
|
@ -1007,10 +1007,10 @@ void DomainServer::sendHeartbeatToIceServer() {
|
||||||
DependencyManager::get<LimitedNodeList>()->sendHeartbeatToIceServer(_iceServerSocket);
|
DependencyManager::get<LimitedNodeList>()->sendHeartbeatToIceServer(_iceServerSocket);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DomainServer::processNodeJSONStatsPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode) {
|
void DomainServer::processNodeJSONStatsPacket(QSharedPointer<NLPacketList> packetList, SharedNodePointer sendingNode) {
|
||||||
auto nodeData = dynamic_cast<DomainServerNodeData*>(sendingNode->getLinkedData());
|
auto nodeData = dynamic_cast<DomainServerNodeData*>(sendingNode->getLinkedData());
|
||||||
if (nodeData) {
|
if (nodeData) {
|
||||||
nodeData->processJSONStatsPacket(*packet);
|
nodeData->processJSONStatsPacket(packetList->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ public slots:
|
||||||
|
|
||||||
void processRequestAssignmentPacket(QSharedPointer<NLPacket> packet);
|
void processRequestAssignmentPacket(QSharedPointer<NLPacket> packet);
|
||||||
void processListRequestPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode);
|
void processListRequestPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode);
|
||||||
void processNodeJSONStatsPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode);
|
void processNodeJSONStatsPacket(QSharedPointer<NLPacketList> packetList, SharedNodePointer sendingNode);
|
||||||
void processPathQueryPacket(QSharedPointer<NLPacket> packet);
|
void processPathQueryPacket(QSharedPointer<NLPacket> packet);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
|
@ -31,9 +31,9 @@ DomainServerNodeData::DomainServerNodeData() :
|
||||||
_paymentIntervalTimer.start();
|
_paymentIntervalTimer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DomainServerNodeData::processJSONStatsPacket(NLPacket& statsPacket) {
|
void DomainServerNodeData::processJSONStatsPacket(QByteArray statsByteArray) {
|
||||||
QVariantMap packetVariantMap = JSONBreakableMarshal::fromStringBuffer(statsPacket.readAll());
|
QJsonObject packetJsonObject = JSONBreakableMarshal::fromByteArray(statsByteArray);
|
||||||
_statsJSONObject = mergeJSONStatsFromNewObject(QJsonObject::fromVariantMap(packetVariantMap), _statsJSONObject);
|
_statsJSONObject = mergeJSONStatsFromNewObject(packetJsonObject, _statsJSONObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject DomainServerNodeData::mergeJSONStatsFromNewObject(const QJsonObject& newObject, QJsonObject destinationObject) {
|
QJsonObject DomainServerNodeData::mergeJSONStatsFromNewObject(const QJsonObject& newObject, QJsonObject destinationObject) {
|
||||||
|
|
|
@ -27,7 +27,7 @@ public:
|
||||||
|
|
||||||
const QJsonObject& getStatsJSONObject() const { return _statsJSONObject; }
|
const QJsonObject& getStatsJSONObject() const { return _statsJSONObject; }
|
||||||
|
|
||||||
void processJSONStatsPacket(NLPacket& packet);
|
void processJSONStatsPacket(QByteArray statsByteArray);
|
||||||
|
|
||||||
void setAssignmentUUID(const QUuid& assignmentUUID) { _assignmentUUID = assignmentUUID; }
|
void setAssignmentUUID(const QUuid& assignmentUUID) { _assignmentUUID = assignmentUUID; }
|
||||||
const QUuid& getAssignmentUUID() const { return _assignmentUUID; }
|
const QUuid& getAssignmentUUID() const { return _assignmentUUID; }
|
||||||
|
|
|
@ -74,7 +74,7 @@ void DomainServerSettingsManager::processSettingsRequestPacket(QSharedPointer<NL
|
||||||
QJsonObject responseObject = responseObjectForType(QString::number(type));
|
QJsonObject responseObject = responseObjectForType(QString::number(type));
|
||||||
auto json = QJsonDocument(responseObject).toJson();
|
auto json = QJsonDocument(responseObject).toJson();
|
||||||
|
|
||||||
auto packetList = std::unique_ptr<NLPacketList>(new NLPacketList(PacketType::DomainSettings, QByteArray(), true, true));
|
auto packetList = NLPacketList::create(PacketType::DomainSettings, QByteArray(), true, true);
|
||||||
|
|
||||||
packetList->write(json);
|
packetList->write(json);
|
||||||
|
|
||||||
|
|
|
@ -142,14 +142,15 @@
|
||||||
#include "SpeechRecognizer.h"
|
#include "SpeechRecognizer.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "ui/AddressBarDialog.h"
|
||||||
#include "ui/AvatarInputs.h"
|
#include "ui/AvatarInputs.h"
|
||||||
#include "ui/DataWebDialog.h"
|
#include "ui/DataWebDialog.h"
|
||||||
#include "ui/DialogsManager.h"
|
#include "ui/DialogsManager.h"
|
||||||
|
#include "ui/FileDialog.h"
|
||||||
#include "ui/LoginDialog.h"
|
#include "ui/LoginDialog.h"
|
||||||
#include "ui/Snapshot.h"
|
#include "ui/Snapshot.h"
|
||||||
#include "ui/StandAloneJSConsole.h"
|
#include "ui/StandAloneJSConsole.h"
|
||||||
#include "ui/Stats.h"
|
#include "ui/Stats.h"
|
||||||
#include "ui/AddressBarDialog.h"
|
|
||||||
#include "ui/UpdateDialog.h"
|
#include "ui/UpdateDialog.h"
|
||||||
#include "ui/overlays/Cube3DOverlay.h"
|
#include "ui/overlays/Cube3DOverlay.h"
|
||||||
|
|
||||||
|
@ -3009,7 +3010,7 @@ int Application::sendNackPackets() {
|
||||||
|
|
||||||
if (node->getActiveSocket() && node->getType() == NodeType::EntityServer) {
|
if (node->getActiveSocket() && node->getType() == NodeType::EntityServer) {
|
||||||
|
|
||||||
NLPacketList nackPacketList(PacketType::OctreeDataNack);
|
auto nackPacketList = NLPacketList::create(PacketType::OctreeDataNack);
|
||||||
|
|
||||||
QUuid nodeUUID = node->getUUID();
|
QUuid nodeUUID = node->getUUID();
|
||||||
|
|
||||||
|
@ -3038,15 +3039,15 @@ int Application::sendNackPackets() {
|
||||||
auto it = missingSequenceNumbers.constBegin();
|
auto it = missingSequenceNumbers.constBegin();
|
||||||
while (it != missingSequenceNumbers.constEnd()) {
|
while (it != missingSequenceNumbers.constEnd()) {
|
||||||
OCTREE_PACKET_SEQUENCE missingNumber = *it;
|
OCTREE_PACKET_SEQUENCE missingNumber = *it;
|
||||||
nackPacketList.writePrimitive(missingNumber);
|
nackPacketList->writePrimitive(missingNumber);
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nackPacketList.getNumPackets()) {
|
if (nackPacketList.getNumPackets()) {
|
||||||
packetsSent += nackPacketList.getNumPackets();
|
packetsSent += nackPacketList->getNumPackets();
|
||||||
|
|
||||||
// send the packet list
|
// send the packet list
|
||||||
nodeList->sendPacketList(nackPacketList, *node);
|
nodeList->sendPacketList(std::move(nackPacketList), *node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//
|
//
|
||||||
// AddressBarDialog.cpp
|
// AddressBarDialog.cpp
|
||||||
|
// interface/src/ui
|
||||||
//
|
//
|
||||||
// Created by Bradley Austin Davis on 2015/04/14
|
// Created by Bradley Austin Davis on 2015/04/14
|
||||||
// Copyright 2015 High Fidelity, Inc.
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//
|
//
|
||||||
// AddressBarDialog.h
|
// AddressBarDialog.h
|
||||||
|
// interface/src/ui
|
||||||
//
|
//
|
||||||
// Created by Bradley Austin Davis on 2015/04/14
|
// Created by Bradley Austin Davis on 2015/04/14
|
||||||
// Copyright 2015 High Fidelity, Inc.
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
class QAction;
|
class QAction;
|
||||||
|
|
||||||
class AddressBarDialog;
|
|
||||||
class AnimationsDialog;
|
class AnimationsDialog;
|
||||||
class AttachmentsDialog;
|
class AttachmentsDialog;
|
||||||
class AudioStatsDialog;
|
class AudioStatsDialog;
|
||||||
|
@ -29,13 +28,11 @@ class BandwidthDialog;
|
||||||
class CachesSizeDialog;
|
class CachesSizeDialog;
|
||||||
class DiskCacheEditor;
|
class DiskCacheEditor;
|
||||||
class LodToolsDialog;
|
class LodToolsDialog;
|
||||||
class LoginDialog;
|
|
||||||
class OctreeStatsDialog;
|
class OctreeStatsDialog;
|
||||||
class PreferencesDialog;
|
class PreferencesDialog;
|
||||||
class ScriptEditorWindow;
|
class ScriptEditorWindow;
|
||||||
class QMessageBox;
|
class QMessageBox;
|
||||||
class DomainConnectionDialog;
|
class DomainConnectionDialog;
|
||||||
class UpdateDialog;
|
|
||||||
|
|
||||||
class DialogsManager : public QObject, public Dependency {
|
class DialogsManager : public QObject, public Dependency {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -94,7 +91,6 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QPointer<AddressBarDialog> _addressBarDialog;
|
|
||||||
QPointer<AnimationsDialog> _animationsDialog;
|
QPointer<AnimationsDialog> _animationsDialog;
|
||||||
QPointer<AttachmentsDialog> _attachmentsDialog;
|
QPointer<AttachmentsDialog> _attachmentsDialog;
|
||||||
QPointer<AudioStatsDialog> _audioStatsDialog;
|
QPointer<AudioStatsDialog> _audioStatsDialog;
|
||||||
|
@ -104,12 +100,10 @@ private:
|
||||||
QPointer<QMessageBox> _ircInfoBox;
|
QPointer<QMessageBox> _ircInfoBox;
|
||||||
QPointer<HMDToolsDialog> _hmdToolsDialog;
|
QPointer<HMDToolsDialog> _hmdToolsDialog;
|
||||||
QPointer<LodToolsDialog> _lodToolsDialog;
|
QPointer<LodToolsDialog> _lodToolsDialog;
|
||||||
QPointer<LoginDialog> _loginDialog;
|
|
||||||
QPointer<OctreeStatsDialog> _octreeStatsDialog;
|
QPointer<OctreeStatsDialog> _octreeStatsDialog;
|
||||||
QPointer<PreferencesDialog> _preferencesDialog;
|
QPointer<PreferencesDialog> _preferencesDialog;
|
||||||
QPointer<ScriptEditorWindow> _scriptEditor;
|
QPointer<ScriptEditorWindow> _scriptEditor;
|
||||||
QPointer<DomainConnectionDialog> _domainConnectionDialog;
|
QPointer<DomainConnectionDialog> _domainConnectionDialog;
|
||||||
QPointer<UpdateDialog> _updateDialog;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_DialogsManager_h
|
#endif // hifi_DialogsManager_h
|
||||||
|
|
|
@ -205,7 +205,7 @@ bool AssetClient::uploadAsset(const QByteArray& data, const QString& extension,
|
||||||
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
||||||
|
|
||||||
if (assetServer) {
|
if (assetServer) {
|
||||||
auto packetList = std::unique_ptr<NLPacketList>(new NLPacketList(PacketType::AssetUpload, QByteArray(), true, true));
|
auto packetList = NLPacketList::create(PacketType::AssetUpload, QByteArray(), true, true);
|
||||||
|
|
||||||
auto messageID = ++_currentID;
|
auto messageID = ++_currentID;
|
||||||
packetList->writePrimitive(messageID);
|
packetList->writePrimitive(messageID);
|
||||||
|
|
|
@ -355,6 +355,12 @@ qint64 LimitedNodeList::sendPacketList(std::unique_ptr<NLPacketList> packetList,
|
||||||
// close the last packet in the list
|
// close the last packet in the list
|
||||||
packetList->closeCurrentPacket();
|
packetList->closeCurrentPacket();
|
||||||
|
|
||||||
|
for (std::unique_ptr<udt::Packet>& packet : packetList->_packets) {
|
||||||
|
NLPacket* nlPacket = static_cast<NLPacket*>(packet.get());
|
||||||
|
collectPacketStats(*nlPacket);
|
||||||
|
fillPacketHeader(*nlPacket);
|
||||||
|
}
|
||||||
|
|
||||||
return _nodeSocket.writePacketList(std::move(packetList), sockAddr);
|
return _nodeSocket.writePacketList(std::move(packetList), sockAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -254,7 +254,7 @@ protected:
|
||||||
qint64 writePacket(const NLPacket& packet, const HifiSockAddr& destinationSockAddr,
|
qint64 writePacket(const NLPacket& packet, const HifiSockAddr& destinationSockAddr,
|
||||||
const QUuid& connectionSecret = QUuid());
|
const QUuid& connectionSecret = QUuid());
|
||||||
void collectPacketStats(const NLPacket& packet);
|
void collectPacketStats(const NLPacket& packet);
|
||||||
void fillPacketHeader(const NLPacket& packet, const QUuid& connectionSecret);
|
void fillPacketHeader(const NLPacket& packet, const QUuid& connectionSecret = QUuid());
|
||||||
|
|
||||||
bool isPacketVerified(const udt::Packet& packet);
|
bool isPacketVerified(const udt::Packet& packet);
|
||||||
bool packetVersionMatch(const udt::Packet& packet);
|
bool packetVersionMatch(const udt::Packet& packet);
|
||||||
|
|
|
@ -13,16 +13,30 @@
|
||||||
|
|
||||||
#include "udt/Packet.h"
|
#include "udt/Packet.h"
|
||||||
|
|
||||||
|
|
||||||
|
std::unique_ptr<NLPacketList> NLPacketList::create(PacketType packetType, QByteArray extendedHeader,
|
||||||
|
bool isReliable, bool isOrdered) {
|
||||||
|
auto nlPacketList = std::unique_ptr<NLPacketList>(new NLPacketList(packetType, extendedHeader,
|
||||||
|
isReliable, isOrdered));
|
||||||
|
nlPacketList->open(WriteOnly);
|
||||||
|
return nlPacketList;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<NLPacketList> NLPacketList::fromPacketList(std::unique_ptr<PacketList> packetList) {
|
||||||
|
auto nlPacketList = std::unique_ptr<NLPacketList>(new NLPacketList(std::move(*packetList.release()))); nlPacketList->open(ReadOnly);
|
||||||
|
return nlPacketList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NLPacketList::NLPacketList(PacketType packetType, QByteArray extendedHeader, bool isReliable, bool isOrdered) :
|
NLPacketList::NLPacketList(PacketType packetType, QByteArray extendedHeader, bool isReliable, bool isOrdered) :
|
||||||
PacketList(packetType, extendedHeader, isReliable, isOrdered)
|
PacketList(packetType, extendedHeader, isReliable, isOrdered)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NLPacketList::NLPacketList(PacketList&& other) : PacketList(other.getType(), other.getExtendedHeader(), other.isReliable(), other.isOrdered()) {
|
NLPacketList::NLPacketList(PacketList&& other) : PacketList(std::move(other)) {
|
||||||
// Update _packets
|
// Update _packets
|
||||||
for (auto& packet : other._packets) {
|
for (auto& packet : _packets) {
|
||||||
auto nlPacket = NLPacket::fromBase(std::move(packet));
|
packet = NLPacket::fromBase(std::move(packet));
|
||||||
_packets.push_back(std::move(nlPacket));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_packets.size() > 0) {
|
if (_packets.size() > 0) {
|
||||||
|
|
|
@ -18,12 +18,17 @@
|
||||||
|
|
||||||
class NLPacketList : public udt::PacketList {
|
class NLPacketList : public udt::PacketList {
|
||||||
public:
|
public:
|
||||||
NLPacketList(PacketType packetType, QByteArray extendedHeader = QByteArray(), bool isReliable = false, bool isOrdered = false);
|
static std::unique_ptr<NLPacketList> create(PacketType packetType, QByteArray extendedHeader = QByteArray(),
|
||||||
NLPacketList(PacketList&& packetList);
|
bool isReliable = false, bool isOrdered = false);
|
||||||
|
|
||||||
|
static std::unique_ptr<NLPacketList> fromPacketList(std::unique_ptr<PacketList>);
|
||||||
|
|
||||||
const QUuid& getSourceID() const { return _sourceID; }
|
const QUuid& getSourceID() const { return _sourceID; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
NLPacketList(PacketType packetType, QByteArray extendedHeader = QByteArray(), bool isReliable = false,
|
||||||
|
bool isOrdered = false);
|
||||||
|
NLPacketList(PacketList&& packetList);
|
||||||
NLPacketList(const NLPacketList& other) = delete;
|
NLPacketList(const NLPacketList& other) = delete;
|
||||||
NLPacketList& operator=(const NLPacketList& other) = delete;
|
NLPacketList& operator=(const NLPacketList& other) = delete;
|
||||||
|
|
||||||
|
|
|
@ -107,20 +107,11 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 NodeList::sendStats(const QJsonObject& statsObject, const HifiSockAddr& destination) {
|
qint64 NodeList::sendStats(const QJsonObject& statsObject, const HifiSockAddr& destination) {
|
||||||
NLPacketList statsPacketList(PacketType::NodeJsonStats);
|
auto statsPacketList = NLPacketList::create(PacketType::NodeJsonStats, QByteArray(), true, true);
|
||||||
|
|
||||||
// get a QStringList using JSONBreakableMarshal
|
statsPacketList->write(JSONBreakableMarshal::toByteArray(statsObject));
|
||||||
QStringList statsStringList = JSONBreakableMarshal::toStringList(statsObject, "");
|
|
||||||
|
|
||||||
// enumerate the resulting strings - pack them and send off packets via NLPacketList
|
sendPacketList(std::move(statsPacketList), destination);
|
||||||
foreach(const QString& statsItem, statsStringList) {
|
|
||||||
QByteArray utf8String = statsItem.toUtf8();
|
|
||||||
utf8String.append('\0');
|
|
||||||
|
|
||||||
statsPacketList.write(utf8String);
|
|
||||||
}
|
|
||||||
|
|
||||||
sendPacketList(statsPacketList, destination);
|
|
||||||
|
|
||||||
// enumerate the resulting strings, breaking them into MTU sized packets
|
// enumerate the resulting strings, breaking them into MTU sized packets
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -247,7 +247,7 @@ void PacketReceiver::handleVerifiedPacketList(std::unique_ptr<udt::PacketList> p
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup an NLPacketList from the PacketList we were passed
|
// setup an NLPacketList from the PacketList we were passed
|
||||||
auto nlPacketList = new NLPacketList(std::move(*packetList));
|
auto nlPacketList = NLPacketList::fromPacketList(std::move(packetList));
|
||||||
|
|
||||||
auto nodeList = DependencyManager::get<LimitedNodeList>();
|
auto nodeList = DependencyManager::get<LimitedNodeList>();
|
||||||
|
|
||||||
|
@ -297,21 +297,21 @@ void PacketReceiver::handleVerifiedPacketList(std::unique_ptr<udt::PacketList> p
|
||||||
success = metaMethod.invoke(listener.first,
|
success = metaMethod.invoke(listener.first,
|
||||||
connectionType,
|
connectionType,
|
||||||
Q_ARG(QSharedPointer<NLPacketList>,
|
Q_ARG(QSharedPointer<NLPacketList>,
|
||||||
QSharedPointer<NLPacketList>(nlPacketList)),
|
QSharedPointer<NLPacketList>(nlPacketList.release())),
|
||||||
Q_ARG(SharedNodePointer, matchingNode));
|
Q_ARG(SharedNodePointer, matchingNode));
|
||||||
|
|
||||||
} else if (metaMethod.parameterTypes().contains(QSHAREDPOINTER_NODE_NORMALIZED)) {
|
} else if (metaMethod.parameterTypes().contains(QSHAREDPOINTER_NODE_NORMALIZED)) {
|
||||||
success = metaMethod.invoke(listener.first,
|
success = metaMethod.invoke(listener.first,
|
||||||
connectionType,
|
connectionType,
|
||||||
Q_ARG(QSharedPointer<NLPacketList>,
|
Q_ARG(QSharedPointer<NLPacketList>,
|
||||||
QSharedPointer<NLPacketList>(nlPacketList)),
|
QSharedPointer<NLPacketList>(nlPacketList.release())),
|
||||||
Q_ARG(QSharedPointer<Node>, matchingNode));
|
Q_ARG(QSharedPointer<Node>, matchingNode));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
success = metaMethod.invoke(listener.first,
|
success = metaMethod.invoke(listener.first,
|
||||||
connectionType,
|
connectionType,
|
||||||
Q_ARG(QSharedPointer<NLPacketList>,
|
Q_ARG(QSharedPointer<NLPacketList>,
|
||||||
QSharedPointer<NLPacketList>(nlPacketList)));
|
QSharedPointer<NLPacketList>(nlPacketList.release())));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
listenerIsDead = true;
|
listenerIsDead = true;
|
||||||
|
@ -323,7 +323,7 @@ void PacketReceiver::handleVerifiedPacketList(std::unique_ptr<udt::PacketList> p
|
||||||
if (listener.first) {
|
if (listener.first) {
|
||||||
success = listener.second.invoke(listener.first,
|
success = listener.second.invoke(listener.first,
|
||||||
Q_ARG(QSharedPointer<NLPacketList>,
|
Q_ARG(QSharedPointer<NLPacketList>,
|
||||||
QSharedPointer<NLPacketList>(nlPacketList)));
|
QSharedPointer<NLPacketList>(nlPacketList.release())));
|
||||||
} else {
|
} else {
|
||||||
listenerIsDead = true;
|
listenerIsDead = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,6 @@ public:
|
||||||
static std::unique_ptr<BasePacket> create(qint64 size = -1);
|
static std::unique_ptr<BasePacket> create(qint64 size = -1);
|
||||||
static std::unique_ptr<BasePacket> fromReceivedPacket(std::unique_ptr<char[]> data, qint64 size,
|
static std::unique_ptr<BasePacket> fromReceivedPacket(std::unique_ptr<char[]> data, qint64 size,
|
||||||
const HifiSockAddr& senderSockAddr);
|
const HifiSockAddr& senderSockAddr);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Current level's header size
|
// Current level's header size
|
||||||
static int localHeaderSize();
|
static int localHeaderSize();
|
||||||
|
@ -72,8 +70,8 @@ public:
|
||||||
virtual bool isSequential() const { return false; }
|
virtual bool isSequential() const { return false; }
|
||||||
virtual bool reset();
|
virtual bool reset();
|
||||||
virtual qint64 size() const { return _payloadCapacity; }
|
virtual qint64 size() const { return _payloadCapacity; }
|
||||||
|
|
||||||
using QIODevice::read;
|
using QIODevice::read; // Bring QIODevice::read methods to scope, otherwise they are hidden by folling method
|
||||||
QByteArray read(qint64 maxSize);
|
QByteArray read(qint64 maxSize);
|
||||||
QByteArray readWithoutCopy(qint64 maxSize); // this can only be used if packet will stay in scope
|
QByteArray readWithoutCopy(qint64 maxSize); // this can only be used if packet will stay in scope
|
||||||
|
|
||||||
|
@ -107,16 +105,16 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T> qint64 BasePacket::peekPrimitive(T* data) {
|
template<typename T> qint64 BasePacket::peekPrimitive(T* data) {
|
||||||
return QIODevice::peek(reinterpret_cast<char*>(data), sizeof(T));
|
return peek(reinterpret_cast<char*>(data), sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> qint64 BasePacket::readPrimitive(T* data) {
|
template<typename T> qint64 BasePacket::readPrimitive(T* data) {
|
||||||
return QIODevice::read(reinterpret_cast<char*>(data), sizeof(T));
|
return read(reinterpret_cast<char*>(data), sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> qint64 BasePacket::writePrimitive(const T& data) {
|
template<typename T> qint64 BasePacket::writePrimitive(const T& data) {
|
||||||
static_assert(!std::is_pointer<T>::value, "T must not be a pointer");
|
static_assert(!std::is_pointer<T>::value, "T must not be a pointer");
|
||||||
return QIODevice::write(reinterpret_cast<const char*>(&data), sizeof(T));
|
return write(reinterpret_cast<const char*>(&data), sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace udt
|
} // namespace udt
|
||||||
|
|
|
@ -15,6 +15,21 @@
|
||||||
|
|
||||||
using namespace udt;
|
using namespace udt;
|
||||||
|
|
||||||
|
std::unique_ptr<PacketList> PacketList::create(PacketType packetType, QByteArray extendedHeader,
|
||||||
|
bool isReliable, bool isOrdered) {
|
||||||
|
auto packetList = std::unique_ptr<PacketList>(new PacketList(packetType, extendedHeader,
|
||||||
|
isReliable, isOrdered));
|
||||||
|
packetList->open(WriteOnly);
|
||||||
|
return packetList;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<PacketList> PacketList::fromReceivedPackets(std::list<std::unique_ptr<Packet>>&& packets) {
|
||||||
|
auto packetList = std::unique_ptr<PacketList>(new PacketList(PacketType::Unknown, QByteArray(), true, true));
|
||||||
|
packetList->_packets = std::move(packets);
|
||||||
|
packetList->open(ReadOnly);
|
||||||
|
return packetList;
|
||||||
|
}
|
||||||
|
|
||||||
PacketList::PacketList(PacketType packetType, QByteArray extendedHeader, bool isReliable, bool isOrdered) :
|
PacketList::PacketList(PacketType packetType, QByteArray extendedHeader, bool isReliable, bool isOrdered) :
|
||||||
_packetType(packetType),
|
_packetType(packetType),
|
||||||
_isReliable(isReliable),
|
_isReliable(isReliable),
|
||||||
|
@ -22,14 +37,15 @@ PacketList::PacketList(PacketType packetType, QByteArray extendedHeader, bool is
|
||||||
_extendedHeader(extendedHeader)
|
_extendedHeader(extendedHeader)
|
||||||
{
|
{
|
||||||
Q_ASSERT_X(!(!_isReliable && _isOrdered), "PacketList", "Unreliable ordered PacketLists are not currently supported");
|
Q_ASSERT_X(!(!_isReliable && _isOrdered), "PacketList", "Unreliable ordered PacketLists are not currently supported");
|
||||||
QIODevice::open(WriteOnly);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketList::PacketList(PacketList&& other) :
|
PacketList::PacketList(PacketList&& other) :
|
||||||
|
_packetType(other._packetType),
|
||||||
_packets(std::move(other._packets)),
|
_packets(std::move(other._packets)),
|
||||||
_packetType(other._packetType)
|
_isReliable(other._isReliable),
|
||||||
|
_isOrdered(other._isOrdered),
|
||||||
|
_extendedHeader(std::move(other._extendedHeader))
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacketList::startSegment() {
|
void PacketList::startSegment() {
|
||||||
|
@ -66,12 +82,6 @@ size_t PacketList::getMessageSize() const {
|
||||||
return totalBytes;
|
return totalBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<PacketList> PacketList::fromReceivedPackets(std::list<std::unique_ptr<Packet>>&& packets) {
|
|
||||||
auto packetList = std::unique_ptr<PacketList>(new PacketList(PacketType::Unknown, QByteArray(), true, true));
|
|
||||||
packetList->_packets = std::move(packets);
|
|
||||||
return packetList;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<Packet> PacketList::createPacket() {
|
std::unique_ptr<Packet> PacketList::createPacket() {
|
||||||
// use the static create method to create a new packet
|
// use the static create method to create a new packet
|
||||||
// If this packet list is supposed to be ordered then we consider this to be part of a message
|
// If this packet list is supposed to be ordered then we consider this to be part of a message
|
||||||
|
@ -94,6 +104,17 @@ std::unique_ptr<Packet> PacketList::createPacketWithExtendedHeader() {
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PacketList::closeCurrentPacket(bool shouldSendEmpty) {
|
||||||
|
if (shouldSendEmpty && !_currentPacket) {
|
||||||
|
_currentPacket = createPacketWithExtendedHeader();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_currentPacket) {
|
||||||
|
// move the current packet to our list of packets
|
||||||
|
_packets.push_back(std::move(_currentPacket));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray PacketList::getMessage() {
|
QByteArray PacketList::getMessage() {
|
||||||
size_t sizeBytes = 0;
|
size_t sizeBytes = 0;
|
||||||
|
|
||||||
|
@ -191,14 +212,3 @@ qint64 PacketList::writeData(const char* data, qint64 maxSize) {
|
||||||
|
|
||||||
return maxSize;
|
return maxSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacketList::closeCurrentPacket(bool shouldSendEmpty) {
|
|
||||||
if (shouldSendEmpty && !_currentPacket) {
|
|
||||||
_currentPacket = createPacketWithExtendedHeader();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_currentPacket) {
|
|
||||||
// move the current packet to our list of packets
|
|
||||||
_packets.push_back(std::move(_currentPacket));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -28,13 +28,9 @@ class Packet;
|
||||||
class PacketList : public QIODevice {
|
class PacketList : public QIODevice {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
PacketList(PacketType packetType, QByteArray extendedHeader = QByteArray(), bool isReliable = false, bool isOrdered = false);
|
static std::unique_ptr<PacketList> create(PacketType packetType, QByteArray extendedHeader = QByteArray(), bool isReliable = false, bool isOrdered = false);
|
||||||
PacketList(PacketList&& other);
|
|
||||||
|
|
||||||
static std::unique_ptr<PacketList> fromReceivedPackets(std::list<std::unique_ptr<Packet>>&& packets);
|
static std::unique_ptr<PacketList> fromReceivedPackets(std::list<std::unique_ptr<Packet>>&& packets);
|
||||||
|
|
||||||
virtual bool isSequential() const { return true; }
|
|
||||||
|
|
||||||
bool isReliable() const { return _isReliable; }
|
bool isReliable() const { return _isReliable; }
|
||||||
bool isOrdered() const { return _isOrdered; }
|
bool isOrdered() const { return _isOrdered; }
|
||||||
|
|
||||||
|
@ -53,20 +49,27 @@ public:
|
||||||
|
|
||||||
QByteArray getMessage();
|
QByteArray getMessage();
|
||||||
|
|
||||||
|
// QIODevice virtual functions
|
||||||
|
virtual bool isSequential() const { return false; }
|
||||||
|
virtual qint64 size() const { return getDataSize(); }
|
||||||
|
|
||||||
template<typename T> qint64 readPrimitive(T* data);
|
template<typename T> qint64 readPrimitive(T* data);
|
||||||
template<typename T> qint64 writePrimitive(const T& data);
|
template<typename T> qint64 writePrimitive(const T& data);
|
||||||
std::list<std::unique_ptr<Packet>> _packets;
|
|
||||||
protected:
|
protected:
|
||||||
virtual qint64 writeData(const char* data, qint64 maxSize);
|
PacketList(PacketType packetType, QByteArray extendedHeader = QByteArray(), bool isReliable = false, bool isOrdered = false);
|
||||||
virtual qint64 readData(char* data, qint64 maxSize) { return 0; }
|
PacketList(PacketList&& other);
|
||||||
PacketType _packetType;
|
|
||||||
|
|
||||||
|
virtual qint64 writeData(const char* data, qint64 maxSize);
|
||||||
|
virtual qint64 readData(char* data, qint64 maxSize) { Q_ASSERT(false); }
|
||||||
|
|
||||||
|
PacketType _packetType;
|
||||||
|
std::list<std::unique_ptr<Packet>> _packets;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class ::LimitedNodeList;
|
friend class ::LimitedNodeList;
|
||||||
friend class Socket;
|
|
||||||
friend class SendQueue;
|
friend class SendQueue;
|
||||||
friend class NLPacketList;
|
friend class Socket;
|
||||||
|
|
||||||
PacketList(const PacketList& other) = delete;
|
PacketList(const PacketList& other) = delete;
|
||||||
PacketList& operator=(const PacketList& other) = delete;
|
PacketList& operator=(const PacketList& other) = delete;
|
||||||
|
@ -91,12 +94,12 @@ private:
|
||||||
|
|
||||||
template <typename T> qint64 PacketList::readPrimitive(T* data) {
|
template <typename T> qint64 PacketList::readPrimitive(T* data) {
|
||||||
static_assert(!std::is_pointer<T>::value, "T must not be a pointer");
|
static_assert(!std::is_pointer<T>::value, "T must not be a pointer");
|
||||||
return QIODevice::read(reinterpret_cast<char*>(data), sizeof(T));
|
return read(reinterpret_cast<char*>(data), sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> qint64 PacketList::writePrimitive(const T& data) {
|
template <typename T> qint64 PacketList::writePrimitive(const T& data) {
|
||||||
static_assert(!std::is_pointer<T>::value, "T must not be a pointer");
|
static_assert(!std::is_pointer<T>::value, "T must not be a pointer");
|
||||||
return QIODevice::write(reinterpret_cast<const char*>(&data), sizeof(T));
|
return write(reinterpret_cast<const char*>(&data), sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> std::unique_ptr<T> PacketList::takeFront() {
|
template<typename T> std::unique_ptr<T> PacketList::takeFront() {
|
||||||
|
|
Loading…
Reference in a new issue