Make NodeJSONStats reliable

This commit is contained in:
Atlante45 2015-09-10 16:26:43 +02:00
parent c4c6e7264e
commit 5808658958
24 changed files with 130 additions and 109 deletions

View file

@ -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>

View file

@ -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"

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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());
} }
} }

View file

@ -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:

View file

@ -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) {

View file

@ -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; }

View file

@ -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);

View file

@ -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);
} }
} }
}); });

View file

@ -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.

View file

@ -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.

View file

@ -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

View file

@ -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);

View file

@ -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);
} }

View file

@ -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);

View file

@ -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) {

View file

@ -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;

View file

@ -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;

View file

@ -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;
} }

View file

@ -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

View file

@ -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));
}
}

View file

@ -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() {