repairs to octree packet receiving in interface

This commit is contained in:
Stephen Birarda 2015-07-13 13:10:57 -07:00
parent 264f39fa59
commit d990420565
18 changed files with 179 additions and 218 deletions

View file

@ -3910,12 +3910,12 @@ void Application::nodeKilled(SharedNodePointer node) {
DependencyManager::get<AvatarManager>()->clearOtherAvatars();
}
}
void Application::trackIncomingOctreePacket(const QByteArray& packet, const SharedNodePointer& sendingNode, bool wasStatsPacket) {
void Application::trackIncomingOctreePacket(NLPacket& packet, SharedNodePointer sendingNode, bool wasStatsPacket) {
// Attempt to identify the sender from its address.
if (sendingNode) {
QUuid nodeUUID = sendingNode->getUUID();
const QUuid& nodeUUID = sendingNode->getUUID();
// now that we know the node ID, let's add these stats to the stats for that node...
_octreeSceneStatsLock.lockForWrite();
@ -3927,7 +3927,7 @@ void Application::trackIncomingOctreePacket(const QByteArray& packet, const Shar
}
}
int Application::processOctreeStats(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode) {
int Application::processOctreeStats(NLPacket& packet, SharedNodePointer sendingNode) {
// But, also identify the sender, and keep track of the contained jurisdiction root for this server
// parse the incoming stats datas stick it in a temporary object for now, while we
@ -3941,10 +3941,10 @@ int Application::processOctreeStats(QSharedPointer<NLPacket> packet, SharedNodeP
_octreeSceneStatsLock.lockForWrite();
if (_octreeServerSceneStats.find(nodeUUID) != _octreeServerSceneStats.end()) {
octreeStats = &_octreeServerSceneStats[nodeUUID];
statsMessageLength = octreeStats->unpackFromPacket(*packet);
statsMessageLength = octreeStats->unpackFromPacket(packet);
} else {
OctreeSceneStats temp;
statsMessageLength = temp.unpackFromPacket(*packet);
statsMessageLength = temp.unpackFromPacket(packet);
octreeStats = &temp;
}
_octreeSceneStatsLock.unlock();

View file

@ -612,8 +612,8 @@ private:
StDev _idleLoopStdev;
float _idleLoopMeasuredJitter;
int processOctreeStats(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode);
void trackIncomingOctreePacket(const QByteArray& packet, const SharedNodePointer& sendingNode, bool wasStatsPacket);
int processOctreeStats(NLPacket& packet, SharedNodePointer sendingNode);
void trackIncomingOctreePacket(NLPacket& packet, SharedNodePointer sendingNode, bool wasStatsPacket);
NodeToJurisdictionMap _entityServerJurisdictions;
NodeToOctreeSceneStats _octreeServerSceneStats;

View file

@ -28,7 +28,7 @@ OctreePacketProcessor::OctreePacketProcessor() {
}
void OctreePacketProcessor::handleOctreePacket(QSharedPointer<NLPacket> packet, SharedNodePointer senderNode) {
queueReceivedPacket(senderNode, packet);
queueReceivedPacket(packet, senderNode);
}
void OctreePacketProcessor::processPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode) {
@ -41,8 +41,6 @@ void OctreePacketProcessor::processPacket(QSharedPointer<NLPacket> packet, Share
qDebug("OctreePacketProcessor::processPacket() packets to process=%d", packetsToProcessCount());
}
int messageLength = packet->getSizeUsed();
Application* app = Application::getInstance();
bool wasStatsPacket = false;
@ -52,60 +50,61 @@ void OctreePacketProcessor::processPacket(QSharedPointer<NLPacket> packet, Share
// immediately following them inside the same packet. So, we process the PacketType_OCTREE_STATS first
// then process any remaining bytes as if it was another packet
if (octreePacketType == PacketType::OctreeStats) {
int statsMessageLength = app->processOctreeStats(packet, sendingNode);
wasStatsPacket = true;
if (messageLength > statsMessageLength) {
mutablePacket = mutablePacket.mid(statsMessageLength);
int statsMessageLength = app->processOctreeStats(*packet, sendingNode);
// TODO: this does not look correct, the goal is to test the packet version for the piggyback, but
// this is testing the version and hash of the original packet
if (!DependencyManager::get<NodeList>()->packetVersionAndHashMatch(packet)) {
return; // bail since piggyback data doesn't match our versioning
}
wasStatsPacket = true;
int piggybackBytes = packet->getSizeUsed() - statsMessageLength;
if (piggybackBytes) {
// construct a new packet from the piggybacked one
std::unique_ptr<char> buffer = std::unique_ptr<char>(new char[piggybackBytes]);
memcpy(buffer.get(), packet->getPayload() + statsMessageLength, piggybackBytes);
auto newPacket = NLPacket::fromReceivedPacket(std::move(buffer), piggybackBytes, packet->getSenderSockAddr());
packet = QSharedPointer<NLPacket>(newPacket.release());
} else {
// Note... stats packets don't have sequence numbers, so we don't want to send those to trackIncomingVoxelPacket()
return; // bail since no piggyback data
}
} // fall through to piggyback message
voxelPacketType = packetTypeForPacket(mutablePacket);
PacketVersion packetVersion = mutablePacket[1];
PacketVersion expectedVersion = versionForPacketType(voxelPacketType);
PacketType::Value packetType = packet->getType();
// check version of piggyback packet against expected version
if (packetVersion != expectedVersion) {
if (packetType != versionForPacketType(packet->getType())) {
static QMultiMap<QUuid, PacketType::Value> versionDebugSuppressMap;
QUuid senderUUID = uuidFromPacketHeader(packet);
if (!versionDebugSuppressMap.contains(senderUUID, voxelPacketType)) {
qDebug() << "Packet version mismatch on" << voxelPacketType << "- Sender"
<< senderUUID << "sent" << (int)packetVersion << "but"
<< (int)expectedVersion << "expected.";
const QUuid& senderUUID = packet->getSourceID();
if (!versionDebugSuppressMap.contains(senderUUID, packet->getType())) {
qDebug() << "Packet version mismatch on" << packetType << "- Sender"
<< senderUUID << "sent" << (int) packetType << "but"
<< (int) versionForPacketType(packetType) << "expected.";
emit packetVersionMismatch();
versionDebugSuppressMap.insert(senderUUID, voxelPacketType);
versionDebugSuppressMap.insert(senderUUID, packetType);
}
return; // bail since piggyback version doesn't match
}
app->trackIncomingOctreePacket(mutablePacket, sendingNode, wasStatsPacket);
app->trackIncomingOctreePacket(*packet, sendingNode, wasStatsPacket);
switch(voxelPacketType) {
switch(packetType) {
case PacketType::EntityErase: {
if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderEntities()) {
app->_entities.processEraseMessage(mutablePacket, sendingNode);
app->_entities.processEraseMessage(*packet, sendingNode);
}
} break;
case PacketType::EntityData: {
if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderEntities()) {
app->_entities.processDatagram(mutablePacket, sendingNode);
app->_entities.processDatagram(*packet, sendingNode);
}
} break;
case PacketType::EnvironmentData: {
app->_environment.parseData(*sendingNode->getActiveSocket(), mutablePacket);
app->_environment.processPacket(*packet);
} break;
default: {

View file

@ -45,7 +45,7 @@
#include "EntitiesRendererLogging.h"
#include "AddressManager.h"
EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState,
EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState,
AbstractScriptingServicesInterface* scriptingServices) :
OctreeRenderer(),
_wantScripts(wantScripts),
@ -75,13 +75,13 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
}
EntityTreeRenderer::~EntityTreeRenderer() {
// NOTE: we don't need to delete _entitiesScriptEngine because it is registered with the application and has a
// NOTE: we don't need to delete _entitiesScriptEngine because it is registered with the application and has a
// signal tied to call it's deleteLater on doneRunning
if (_sandboxScriptEngine) {
// TODO: consider reworking how _sandboxScriptEngine is managed. It's treated differently than _entitiesScriptEngine
// because we don't call registerScriptEngineWithApplicationServices() for it. This implementation is confusing and
// potentially error prone because it's not a full fledged ScriptEngine that has been fully connected to the
// application. We did this so that scripts that were ill-formed could be evaluated but not execute against the
// because we don't call registerScriptEngineWithApplicationServices() for it. This implementation is confusing and
// potentially error prone because it's not a full fledged ScriptEngine that has been fully connected to the
// application. We did this so that scripts that were ill-formed could be evaluated but not execute against the
// application services. But this means it's shutdown behavior is different from other ScriptEngines
delete _sandboxScriptEngine;
_sandboxScriptEngine = NULL;
@ -119,7 +119,7 @@ void EntityTreeRenderer::init() {
}
// make sure our "last avatar position" is something other than our current position, so that on our
// first chance, we'll check for enter/leave entity events.
// first chance, we'll check for enter/leave entity events.
_lastAvatarPosition = _viewState->getAvatarPosition() + glm::vec3((float)TREE_SCALE);
connect(entityTree, &EntityTree::deletingEntity, this, &EntityTreeRenderer::deletingEntity, Qt::QueuedConnection);
@ -138,7 +138,7 @@ void EntityTreeRenderer::scriptContentsAvailable(const QUrl& url, const QString&
_waitingOnPreload.remove(url);
foreach(EntityItemID entityID, entityIDs) {
checkAndCallPreload(entityID);
}
}
}
}
@ -154,7 +154,7 @@ QScriptValue EntityTreeRenderer::loadEntityScript(const EntityItemID& entityItem
}
QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorText, bool& isURL, bool& isPending, QUrl& urlOut,
QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorText, bool& isURL, bool& isPending, QUrl& urlOut,
bool& reload) {
isPending = false;
QUrl url(scriptMaybeURLorText);
@ -353,7 +353,7 @@ void EntityTreeRenderer::checkEnterLeaveEntities() {
// Note: at this point we don't need to worry about the tree being locked, because we only deal with
// EntityItemIDs from here. The loadEntityScript() method is robust against attempting to load scripts
// for entity IDs that no longer exist.
// for entity IDs that no longer exist.
// for all of our previous containing entities, if they are no longer containing then send them a leave event
foreach(const EntityItemID& entityID, _currentEntitiesInside) {
@ -400,7 +400,7 @@ void EntityTreeRenderer::leaveAllEntities() {
_currentEntitiesInside.clear();
// make sure our "last avatar position" is something other than our current position, so that on our
// first chance, we'll check for enter/leave entity events.
// first chance, we'll check for enter/leave entity events.
_lastAvatarPosition = _viewState->getAvatarPosition() + glm::vec3((float)TREE_SCALE);
}
}
@ -513,7 +513,7 @@ const FBXGeometry* EntityTreeRenderer::getGeometryForEntity(EntityItemPointer en
const FBXGeometry* result = NULL;
if (entityItem->getType() == EntityTypes::Model) {
std::shared_ptr<RenderableModelEntityItem> modelEntityItem =
std::shared_ptr<RenderableModelEntityItem> modelEntityItem =
std::dynamic_pointer_cast<RenderableModelEntityItem>(entityItem);
assert(modelEntityItem); // we need this!!!
Model* model = modelEntityItem->getModel(this);
@ -527,7 +527,7 @@ const FBXGeometry* EntityTreeRenderer::getGeometryForEntity(EntityItemPointer en
const Model* EntityTreeRenderer::getModelForEntityItem(EntityItemPointer entityItem) {
const Model* result = NULL;
if (entityItem->getType() == EntityTypes::Model) {
std::shared_ptr<RenderableModelEntityItem> modelEntityItem =
std::shared_ptr<RenderableModelEntityItem> modelEntityItem =
std::dynamic_pointer_cast<RenderableModelEntityItem>(entityItem);
result = modelEntityItem->getModel(this);
}
@ -538,7 +538,7 @@ const FBXGeometry* EntityTreeRenderer::getCollisionGeometryForEntity(EntityItemP
const FBXGeometry* result = NULL;
if (entityItem->getType() == EntityTypes::Model) {
std::shared_ptr<RenderableModelEntityItem> modelEntityItem =
std::shared_ptr<RenderableModelEntityItem> modelEntityItem =
std::dynamic_pointer_cast<RenderableModelEntityItem>(entityItem);
if (modelEntityItem->hasCompoundShapeURL()) {
Model* model = modelEntityItem->getModel(this);
@ -678,20 +678,20 @@ float EntityTreeRenderer::getSizeScale() const {
return _viewState->getSizeScale();
}
int EntityTreeRenderer::getBoundaryLevelAdjust() const {
int EntityTreeRenderer::getBoundaryLevelAdjust() const {
return _viewState->getBoundaryLevelAdjust();
}
void EntityTreeRenderer::processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) {
static_cast<EntityTree*>(_tree)->processEraseMessage(dataByteArray, sourceNode);
void EntityTreeRenderer::processEraseMessage(NLPacket& packet, const SharedNodePointer& sourceNode) {
static_cast<EntityTree*>(_tree)->processEraseMessage(packet, sourceNode);
}
Model* EntityTreeRenderer::allocateModel(const QString& url, const QString& collisionUrl) {
Model* model = NULL;
// Make sure we only create and delete models on the thread that owns the EntityTreeRenderer
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "allocateModel", Qt::BlockingQueuedConnection,
QMetaObject::invokeMethod(this, "allocateModel", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(Model*, model),
Q_ARG(const QString&, url));
@ -715,7 +715,7 @@ Model* EntityTreeRenderer::updateModel(Model* original, const QString& newUrl, c
// Before we do any creating or deleting, make sure we're on our renderer thread
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "updateModel", Qt::BlockingQueuedConnection,
QMetaObject::invokeMethod(this, "updateModel", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(Model*, model),
Q_ARG(Model*, original),
Q_ARG(const QString&, newUrl));
@ -756,7 +756,7 @@ void EntityTreeRenderer::deleteReleasedModels() {
}
}
RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType,
RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType,
bool precisionPicking) {
RayToEntityIntersectionResult result;
if (_tree) {
@ -764,8 +764,8 @@ RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(cons
OctreeElement* element;
EntityItemPointer intersectedEntity = NULL;
result.intersects = entityTree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face,
(void**)&intersectedEntity, lockType, &result.accurate,
result.intersects = entityTree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face,
(void**)&intersectedEntity, lockType, &result.accurate,
precisionPicking);
if (result.intersects && intersectedEntity) {
result.entityID = intersectedEntity->getEntityItemID();
@ -778,15 +778,15 @@ RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(cons
}
void EntityTreeRenderer::connectSignalsToSlots(EntityScriptingInterface* entityScriptingInterface) {
connect(this, &EntityTreeRenderer::mousePressOnEntity, entityScriptingInterface,
connect(this, &EntityTreeRenderer::mousePressOnEntity, entityScriptingInterface,
[=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId){
entityScriptingInterface->mousePressOnEntity(intersection.entityID, MouseEvent(*event, deviceId));
});
connect(this, &EntityTreeRenderer::mouseMoveOnEntity, entityScriptingInterface,
connect(this, &EntityTreeRenderer::mouseMoveOnEntity, entityScriptingInterface,
[=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId) {
entityScriptingInterface->mouseMoveOnEntity(intersection.entityID, MouseEvent(*event, deviceId));
});
connect(this, &EntityTreeRenderer::mouseReleaseOnEntity, entityScriptingInterface,
connect(this, &EntityTreeRenderer::mouseReleaseOnEntity, entityScriptingInterface,
[=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId) {
entityScriptingInterface->mouseReleaseOnEntity(intersection.entityID, MouseEvent(*event, deviceId));
});
@ -966,7 +966,7 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event, unsigned int deviceI
} else {
// handle the hover logic...
// if we were previously hovering over an entity, and we're no longer hovering over any entity then we need to
// if we were previously hovering over an entity, and we're no longer hovering over any entity then we need to
// send the hover leave for our previous entity
if (!_currentHoverOverEntityID.isInvalidID()) {
emit hoverLeaveEntity(_currentHoverOverEntityID, MouseEvent(*event, deviceID));

View file

@ -38,7 +38,7 @@ public:
class EntityTreeRenderer : public OctreeRenderer, public EntityItemFBXService, public ScriptUser {
Q_OBJECT
public:
EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState,
EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState,
AbstractScriptingServicesInterface* scriptingServices);
virtual ~EntityTreeRenderer();
@ -55,7 +55,7 @@ public:
EntityTree* getTree() { return static_cast<EntityTree*>(_tree); }
void processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode);
void processEraseMessage(NLPacket& packet, const SharedNodePointer& sourceNode);
virtual void init();
virtual void render(RenderArgs* renderArgs) override;
@ -71,7 +71,7 @@ public:
Q_INVOKABLE Model* allocateModel(const QString& url, const QString& collisionUrl);
/// if a renderable entity item needs to update the URL of a model, we will handle that for the entity
Q_INVOKABLE Model* updateModel(Model* original, const QString& newUrl, const QString& collisionUrl);
Q_INVOKABLE Model* updateModel(Model* original, const QString& newUrl, const QString& collisionUrl);
/// if a renderable entity item is done with a model, it should return it to us
void releaseModel(Model* model);
@ -136,7 +136,7 @@ private:
QList<Model*> _releasedModels;
void renderProxies(EntityItemPointer entity, RenderArgs* args);
RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType,
RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType,
bool precisionPicking);
EntityItemID _currentHoverOverEntityID;

View file

@ -128,8 +128,8 @@ void EntityItemProperties::setSittingPoints(const QVector<SittingPoint>& sitting
}
}
bool EntityItemProperties::animationSettingsChanged() const {
return _animationSettingsChanged;
bool EntityItemProperties::animationSettingsChanged() const {
return _animationSettingsChanged;
}
void EntityItemProperties::setAnimationSettings(const QString& value) {
@ -900,11 +900,14 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, Ent
//
// TODO: Implement support for script and visible properties.
//
bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int bytesToRead, int& processedBytes,
bool EntityItemProperties::decodeEntityEditPacket(NLPacket& packet, int& processedBytes,
EntityItemID& entityID, EntityItemProperties& properties) {
bool valid = false;
const unsigned char* data = reinterpret_cast<const unsigned char*>(packet.getPayload());
const unsigned char* dataAt = data;
int bytesToRead = packet.getSizeUsed();
processedBytes = 0;
// the first part of the data is an octcode, this is a required element of the edit packet format, but we don't

View file

@ -179,8 +179,8 @@ public:
static bool encodeEraseEntityMessage(const EntityItemID& entityItemID, QByteArray& buffer);
static bool decodeEntityEditPacket(const unsigned char* data, int bytesToRead, int& processedBytes,
EntityItemID& entityID, EntityItemProperties& properties);
static bool decodeEntityEditPacket(NLPacket& packet, int& processedBytes,
EntityItemID& entityID, EntityItemProperties& properties);
bool glowLevelChanged() const { return _glowLevelChanged; }
bool localRenderAlphaChanged() const { return _localRenderAlphaChanged; }

View file

@ -26,7 +26,7 @@
#include "LogHandler.h"
EntityTree::EntityTree(bool shouldReaverage) :
EntityTree::EntityTree(bool shouldReaverage) :
Octree(shouldReaverage),
_fbxService(NULL),
_simulation(NULL)
@ -568,8 +568,8 @@ EntityItemPointer EntityTree::findEntityByEntityItemID(const EntityItemID& entit
return foundEntity;
}
int EntityTree::processEditPacketData(PacketType::Value packetType, const unsigned char* packetData, int packetLength,
const unsigned char* editData, int maxLength, const SharedNodePointer& senderNode) {
int EntityTree::processEditPacketData(NLPacket& packet, const unsigned char* editData, int maxLength,
const SharedNodePointer& senderNode) {
if (!getIsServer()) {
qCDebug(entities) << "UNEXPECTED!!! processEditPacketData() should only be called on a server tree.";
@ -578,9 +578,9 @@ int EntityTree::processEditPacketData(PacketType::Value packetType, const unsign
int processedBytes = 0;
// we handle these types of "edit" packets
switch (packetType) {
switch (packet.getType()) {
case PacketType::EntityErase: {
QByteArray dataByteArray((const char*)editData, maxLength);
QByteArray dataByteArray = QByteArray::fromRawData(reinterpret_cast<const char*>(editData), maxLength);
processedBytes = processEraseMessageDetails(dataByteArray, senderNode);
break;
}
@ -598,8 +598,8 @@ int EntityTree::processEditPacketData(PacketType::Value packetType, const unsign
EntityItemID entityItemID;
EntityItemProperties properties;
startDecode = usecTimestampNow();
bool validEditPacket = EntityItemProperties::decodeEntityEditPacket(editData, maxLength,
processedBytes, entityItemID, properties);
bool validEditPacket = EntityItemProperties::decodeEntityEditPacket(packet, processedBytes,
entityItemID, properties);
endDecode = usecTimestampNow();
// If we got a valid edit packet, then it could be a new entity or it could be an update to
@ -609,7 +609,7 @@ int EntityTree::processEditPacketData(PacketType::Value packetType, const unsign
startLookup = usecTimestampNow();
EntityItemPointer existingEntity = findEntityByEntityItemID(entityItemID);
endLookup = usecTimestampNow();
if (existingEntity && packetType == PacketType::EntityEdit) {
if (existingEntity && packet.getType() == PacketType::EntityEdit) {
// if the EntityItem exists, then update it
startLogging = usecTimestampNow();
if (wantEditLogging()) {
@ -623,7 +623,7 @@ int EntityTree::processEditPacketData(PacketType::Value packetType, const unsign
existingEntity->markAsChangedOnServer();
endUpdate = usecTimestampNow();
_totalUpdates++;
} else if (packetType == PacketType::EntityAdd) {
} else if (packet.getType() == PacketType::EntityAdd) {
if (senderNode->getCanRez()) {
// this is a new entity... assign a new entityID
properties.setCreated(properties.getLastEdited());
@ -651,7 +651,7 @@ int EntityTree::processEditPacketData(PacketType::Value packetType, const unsign
} else {
static QString repeatedMessage =
LogHandler::getInstance().addRepeatedMessageRegex("^Add or Edit failed.*");
qCDebug(entities) << "Add or Edit failed." << packetType << existingEntity.get();
qCDebug(entities) << "Add or Edit failed." << packet.getType() << existingEntity.get();
}
}
@ -854,45 +854,26 @@ void EntityTree::forgetEntitiesDeletedBefore(quint64 sinceTime) {
// TODO: consider consolidating processEraseMessageDetails() and processEraseMessage()
int EntityTree::processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) {
int EntityTree::processEraseMessage(NLPacket& packet, const SharedNodePointer& sourceNode) {
lockForWrite();
const unsigned char* packetData = (const unsigned char*)dataByteArray.constData();
const unsigned char* dataAt = packetData;
size_t packetLength = dataByteArray.size();
size_t numBytesPacketHeader = numBytesForPacketHeader(dataByteArray);
size_t processedBytes = numBytesPacketHeader;
dataAt += numBytesPacketHeader;
packet.seek(sizeof(OCTREE_PACKET_FLAGS) + sizeof(OCTREE_PACKET_SEQUENCE) + sizeof(OCTREE_PACKET_SENT_TIME));
dataAt += sizeof(OCTREE_PACKET_FLAGS);
processedBytes += sizeof(OCTREE_PACKET_FLAGS);
dataAt += sizeof(OCTREE_PACKET_SEQUENCE);
processedBytes += sizeof(OCTREE_PACKET_SEQUENCE);
dataAt += sizeof(OCTREE_PACKET_SENT_TIME);
processedBytes += sizeof(OCTREE_PACKET_SENT_TIME);
uint16_t numberOfIds = 0; // placeholder for now
memcpy(&numberOfIds, dataAt, sizeof(numberOfIds));
dataAt += sizeof(numberOfIds);
processedBytes += sizeof(numberOfIds);
if (numberOfIds > 0) {
uint16_t numberOfIDs = 0; // placeholder for now
packet.readPrimitive(&numberOfIDs);
if (numberOfIDs > 0) {
QSet<EntityItemID> entityItemIDsToDelete;
for (size_t i = 0; i < numberOfIds; i++) {
for (size_t i = 0; i < numberOfIDs; i++) {
if (processedBytes + NUM_BYTES_RFC4122_UUID > packetLength) {
if (NUM_BYTES_RFC4122_UUID > packet.bytesAvailable()) {
qCDebug(entities) << "EntityTree::processEraseMessage().... bailing because not enough bytes in buffer";
break; // bail to prevent buffer overflow
}
QByteArray encodedID = dataByteArray.mid(processedBytes, NUM_BYTES_RFC4122_UUID);
QUuid entityID = QUuid::fromRfc4122(encodedID);
dataAt += encodedID.size();
processedBytes += encodedID.size();
QUuid entityID = QUuid::fromRfc4122(packet.read(NUM_BYTES_RFC4122_UUID));
EntityItemID entityItemID(entityID);
entityItemIDsToDelete << entityItemID;
@ -904,7 +885,7 @@ int EntityTree::processEraseMessage(const QByteArray& dataByteArray, const Share
deleteEntities(entityItemIDsToDelete, true, true);
}
unlock();
return processedBytes;
return packet.pos();
}
// This version skips over the header

View file

@ -66,8 +66,8 @@ public:
virtual bool canProcessVersion(PacketVersion thisVersion) const
{ return thisVersion >= VERSION_ENTITIES_USE_METERS_AND_RADIANS; }
virtual bool handlesEditPacketType(PacketType::Value packetType) const;
virtual int processEditPacketData(PacketType::Value packetType, const unsigned char* packetData, int packetLength,
const unsigned char* editData, int maxLength, const SharedNodePointer& senderNode);
virtual int processEditPacketData(NLPacket& packet, const unsigned char* editData, int maxLength,
const SharedNodePointer& senderNode);
virtual bool rootElementHasData() const { return true; }
@ -133,8 +133,8 @@ public:
bool& hasMore);
void forgetEntitiesDeletedBefore(quint64 sinceTime);
int processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode);
int processEraseMessageDetails(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode);
int processEraseMessage(NLPacket& packet, const SharedNodePointer& sourceNode);
int processEraseMessageDetails(const QByteArray& buffer, const SharedNodePointer& sourceNode);
EntityItemFBXService* getFBXService() const { return _fbxService; }
void setFBXService(EntityItemFBXService* service) { _fbxService = service; }
@ -186,9 +186,9 @@ public:
virtual quint64 getAverageLoggingTime() const { return _totalEditMessages == 0 ? 0 : _totalLoggingTime / _totalEditMessages; }
void trackIncomingEntityLastEdited(quint64 lastEditedTime, int bytesRead);
quint64 getAverageEditDeltas() const
quint64 getAverageEditDeltas() const
{ return _totalTrackedEdits == 0 ? 0 : _totalEditDeltas / _totalTrackedEdits; }
quint64 getAverageEditBytes() const
quint64 getAverageEditBytes() const
{ return _totalTrackedEdits == 0 ? 0 : _totalEditBytes / _totalTrackedEdits; }
quint64 getMaxEditDelta() const { return _maxEditDelta; }
quint64 getTotalTrackedEdits() const { return _totalTrackedEdits; }

View file

@ -40,6 +40,6 @@ void EntityTreeHeadlessViewer::update() {
}
}
void EntityTreeHeadlessViewer::processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) {
static_cast<EntityTree*>(_tree)->processEraseMessage(dataByteArray, sourceNode);
void EntityTreeHeadlessViewer::processEraseMessage(NLPacket& packet, const SharedNodePointer& sourceNode) {
static_cast<EntityTree*>(_tree)->processEraseMessage(packet, sourceNode);
}

View file

@ -38,7 +38,7 @@ public:
EntityTree* getTree() { return (EntityTree*)_tree; }
void processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode);
void processEraseMessage(NLPacket& packet, const SharedNodePointer& sourceNode);
virtual void init();

View file

@ -229,12 +229,12 @@ public:
// own definition. Implement these to allow your octree based server to support editing
virtual bool getWantSVOfileVersions() const { return false; }
virtual PacketType::Value expectedDataPacketType() const { return PacketType::Unknown; }
virtual bool canProcessVersion(PacketVersion thisVersion) const {
virtual bool canProcessVersion(PacketVersion thisVersion) const {
return thisVersion == versionForPacketType(expectedDataPacketType()); }
virtual PacketVersion expectedVersion() const { return versionForPacketType(expectedDataPacketType()); }
virtual bool handlesEditPacketType(PacketType::Value packetType) const { return false; }
virtual int processEditPacketData(PacketType::Value packetType, const unsigned char* packetData, int packetLength,
const unsigned char* editData, int maxLength, const SharedNodePointer& sourceNode) { return 0; }
virtual int processEditPacketData(NLPacket& packet, const unsigned char* editData, int maxLength,
const SharedNodePointer& sourceNode) { return 0; }
virtual bool recurseChildrenWithData() const { return true; }
virtual bool rootElementHasData() const { return false; }
@ -304,16 +304,16 @@ public:
} lockType;
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
OctreeElement*& node, float& distance, BoxFace& face,
OctreeElement*& node, float& distance, BoxFace& face,
void** intersectedObject = NULL,
Octree::lockType lockType = Octree::TryLock,
bool* accurateResult = NULL,
Octree::lockType lockType = Octree::TryLock,
bool* accurateResult = NULL,
bool precisionPicking = false);
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject = NULL,
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject = NULL,
Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL);
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration,
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration,
Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL);
/// \param cube query cube in world-frame (meters)
@ -323,7 +323,7 @@ public:
/// \param point query point in world-frame (meters)
/// \param lockType how to lock the tree (Lock, TryLock, NoLock)
/// \param[out] accurateResult pointer to output result, will be set "true" or "false" if non-null
OctreeElement* getElementEnclosingPoint(const glm::vec3& point,
OctreeElement* getElementEnclosingPoint(const glm::vec3& point,
Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL);
// Note: this assumes the fileFormat is the HIO individual voxels code files
@ -411,7 +411,7 @@ protected:
QReadWriteLock _lock;
bool _isViewing;
bool _isViewing;
bool _isServer;
};

View file

@ -40,15 +40,15 @@ OctreeRenderer::~OctreeRenderer() {
}
}
void OctreeRenderer::setTree(Octree* newTree) {
void OctreeRenderer::setTree(Octree* newTree) {
if (_tree && _managedTree) {
delete _tree;
_managedTree = false;
}
_tree = newTree;
_tree = newTree;
}
void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) {
void OctreeRenderer::processDatagram(NLPacket& packet, SharedNodePointer sourceNode) {
bool extraDebugging = false;
if (extraDebugging) {
@ -61,30 +61,21 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar
}
bool showTimingDetails = false; // Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showTimingDetails, "OctreeRenderer::processDatagram()",showTimingDetails);
PerformanceWarning warn(showTimingDetails, "OctreeRenderer::processDatagram()", showTimingDetails);
unsigned int packetLength = dataByteArray.size();
PacketType::Value command = packetTypeForPacket(dataByteArray);
unsigned int numBytesPacketHeader = numBytesForPacketHeader(dataByteArray);
QUuid sourceUUID = uuidFromPacketHeader(dataByteArray);
PacketType::Value expectedType = getExpectedPacketType();
// packetVersion is the second byte
PacketVersion packetVersion = dataByteArray[1];
if(command == expectedType) {
if (packet.getType() == getExpectedPacketType()) {
PerformanceWarning warn(showTimingDetails, "OctreeRenderer::processDatagram expected PacketType", showTimingDetails);
// if we are getting inbound packets, then our tree is also viewing, and we should remember that fact.
_tree->setIsViewing(true);
const unsigned char* dataAt = reinterpret_cast<const unsigned char*>(dataByteArray.data()) + numBytesPacketHeader;
OCTREE_PACKET_FLAGS flags;
packet.readPrimitive(&flags);
OCTREE_PACKET_SEQUENCE sequence;
packet.readPrimitive(&sequence);
OCTREE_PACKET_FLAGS flags = (*(OCTREE_PACKET_FLAGS*)(dataAt));
dataAt += sizeof(OCTREE_PACKET_FLAGS);
OCTREE_PACKET_SEQUENCE sequence = (*(OCTREE_PACKET_SEQUENCE*)dataAt);
dataAt += sizeof(OCTREE_PACKET_SEQUENCE);
OCTREE_PACKET_SENT_TIME sentAt = (*(OCTREE_PACKET_SENT_TIME*)dataAt);
dataAt += sizeof(OCTREE_PACKET_SENT_TIME);
OCTREE_PACKET_SENT_TIME sentAt;
packet.readPrimitive(&sentAt);
bool packetIsColored = oneAtBit(flags, PACKET_IS_COLOR_BIT);
bool packetIsCompressed = oneAtBit(flags, PACKET_IS_COMPRESSED_BIT);
@ -94,13 +85,12 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar
int flightTime = arrivedAt - sentAt + clockSkew;
OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0;
unsigned int dataBytes = packetLength - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE);
if (extraDebugging) {
qCDebug(octree, "OctreeRenderer::processDatagram() ... Got Packet Section"
" color:%s compressed:%s sequence: %u flight:%d usec size:%u data:%u",
" color:%s compressed:%s sequence: %u flight:%d usec size:%lld data:%lld",
debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed),
sequence, flightTime, packetLength, dataBytes);
sequence, flightTime, packet.getSizeWithHeader(), packet.bytesAvailable());
}
_packetsInLastWindow++;
@ -111,42 +101,48 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar
quint64 totalWaitingForLock = 0;
quint64 totalUncompress = 0;
quint64 totalReadBitsteam = 0;
const QUuid& sourceUUID = packet.getSourceID();
int subsection = 1;
while (dataBytes > 0) {
bool error = false;
while (packet.bytesAvailable() && !error) {
if (packetIsCompressed) {
if (dataBytes > sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE)) {
sectionLength = (*(OCTREE_PACKET_INTERNAL_SECTION_SIZE*)dataAt);
dataAt += sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE);
dataBytes -= sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE);
if (packet.bytesAvailable() > sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE)) {
packet.readPrimitive(&sectionLength);
} else {
sectionLength = 0;
dataBytes = 0; // stop looping something is wrong
error = true;
}
} else {
sectionLength = dataBytes;
sectionLength = packet.bytesAvailable();
}
if (sectionLength) {
// ask the VoxelTree to read the bitstream into the tree
ReadBitstreamToTreeParams args(packetIsColored ? WANT_COLOR : NO_COLOR, WANT_EXISTS_BITS, NULL,
sourceUUID, sourceNode, false, packetVersion);
ReadBitstreamToTreeParams args(packetIsColored ? WANT_COLOR : NO_COLOR, WANT_EXISTS_BITS, NULL,
sourceUUID, sourceNode, false, packet.getVersion());
quint64 startLock = usecTimestampNow();
// FIXME STUTTER - there may be an opportunity to bump this lock outside of the
// loop to reduce the amount of locking/unlocking we're doing
_tree->lockForWrite();
quint64 startUncompress = usecTimestampNow();
OctreePacketData packetData(packetIsCompressed);
packetData.loadFinalizedContent(dataAt, sectionLength);
packetData.loadFinalizedContent(reinterpret_cast<unsigned char*>(packet.getPayload() + packet.pos()),
sectionLength);
if (extraDebugging) {
qCDebug(octree, "OctreeRenderer::processDatagram() ... Got Packet Section"
" color:%s compressed:%s sequence: %u flight:%d usec size:%u data:%u"
" color:%s compressed:%s sequence: %u flight:%d usec size:%lld data:%lld"
" subsection:%d sectionLength:%d uncompressed:%d",
debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed),
sequence, flightTime, packetLength, dataBytes, subsection, sectionLength,
sequence, flightTime, packet.getSizeWithHeader(), packet.bytesAvailable(), subsection, sectionLength,
packetData.getUncompressedSize());
}
if (extraDebugging) {
qCDebug(octree) << "OctreeRenderer::processDatagram() ******* START _tree->readBitstreamToTree()...";
}
@ -158,8 +154,8 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar
}
_tree->unlock();
dataBytes -= sectionLength;
dataAt += sectionLength;
// seek forwards in packet
packet.seek(packet.pos() + sectionLength);
elementsPerPacket += args.elementsPerPacket;
entitiesPerPacket += args.entitiesPerPacket;
@ -228,10 +224,10 @@ void OctreeRenderer::render(RenderArgs* renderArgs) {
}
}
void OctreeRenderer::clear() {
void OctreeRenderer::clear() {
if (_tree) {
_tree->lockForWrite();
_tree->eraseAllOctreeElements();
_tree->eraseAllOctreeElements();
_tree->unlock();
}
}

View file

@ -45,7 +45,7 @@ public:
virtual void setTree(Octree* newTree);
/// process incoming data
virtual void processDatagram(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode);
virtual void processDatagram(NLPacket& packet, SharedNodePointer sourceNode);
/// initialize and GPU/rendering related resources
virtual void init();

View file

@ -747,20 +747,17 @@ const char* OctreeSceneStats::getItemValue(Item item) {
return _itemValueBuffer;
}
void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet,
bool wasStatsPacket, int nodeClockSkewUsec) {
void OctreeSceneStats::trackIncomingOctreePacket(NLPacket& packet, bool wasStatsPacket, int nodeClockSkewUsec) {
const bool wantExtraDebugging = false;
int numBytesPacketHeader = numBytesForPacketHeader(packet);
const unsigned char* dataAt = reinterpret_cast<const unsigned char*>(packet.data()) + numBytesPacketHeader;
// skip past the flags
packet.seek(sizeof(OCTREE_PACKET_FLAGS));
OCTREE_PACKET_SEQUENCE sequence;
packet.readPrimitive(&sequence);
//VOXEL_PACKET_FLAGS flags = (*(VOXEL_PACKET_FLAGS*)(dataAt));
dataAt += sizeof(OCTREE_PACKET_FLAGS);
OCTREE_PACKET_SEQUENCE sequence = (*(OCTREE_PACKET_SEQUENCE*)dataAt);
dataAt += sizeof(OCTREE_PACKET_SEQUENCE);
OCTREE_PACKET_SENT_TIME sentAt = (*(OCTREE_PACKET_SENT_TIME*)dataAt);
dataAt += sizeof(OCTREE_PACKET_SENT_TIME);
OCTREE_PACKET_SENT_TIME sentAt;
packet.readPrimitive(&sentAt);
//bool packetIsColored = oneAtBit(flags, PACKET_IS_COLOR_BIT);
//bool packetIsCompressed = oneAtBit(flags, PACKET_IS_COMPRESSED_BIT);
@ -792,8 +789,8 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet,
// track packets here...
_incomingPacket++;
_incomingBytes += packet.size();
_incomingBytes += packet.getSizeWithHeader();
if (!wasStatsPacket) {
_incomingWastedBytes += (MAX_PACKET_SIZE - packet.size());
_incomingWastedBytes += (MAX_PACKET_SIZE - packet.getSizeWithHeader());
}
}

View file

@ -160,7 +160,7 @@ public:
quint64 getLastFullTotalBytes() const { return _lastFullTotalBytes; }
// Used in client implementations to track individual octree packets
void trackIncomingOctreePacket(const QByteArray& packet, bool wasStatsPacket, int nodeClockSkewUsec);
void trackIncomingOctreePacket(NLPacket& packet, bool wasStatsPacket, int nodeClockSkewUsec);
quint32 getIncomingPackets() const { return _incomingPacket; }
quint64 getIncomingBytes() const { return _incomingBytes; }

View file

@ -28,15 +28,6 @@
#include "SkyFromAtmosphere_vert.h"
#include "SkyFromAtmosphere_frag.h"
uint qHash(const HifiSockAddr& sockAddr) {
if (sockAddr.getAddress().isNull()) {
return 0; // shouldn't happen, but if it does, zero is a perfectly valid hash
}
quint32 address = sockAddr.getAddress().toIPv4Address();
return sockAddr.getPort() + qHash(QByteArray::fromRawData((char*) &address,
sizeof(address)));
}
Environment::Environment()
: _initialized(false) {
}
@ -53,7 +44,7 @@ void Environment::init() {
setupAtmosphereProgram(SkyFromAtmosphere_vert, SkyFromAtmosphere_frag, _skyFromAtmosphereProgram, _skyFromAtmosphereUniformLocations);
// start off with a default-constructed environment data
_data[HifiSockAddr()][0];
_data[QUuid()][0];
_initialized = true;
}
@ -98,10 +89,10 @@ void Environment::setupAtmosphereProgram(const char* vertSource, const char* fra
void Environment::resetToDefault() {
_data.clear();
_data[HifiSockAddr()][0];
_data[QUuid()][0];
}
void Environment::renderAtmospheres(gpu::Batch& batch, ViewFrustum& camera) {
void Environment::renderAtmospheres(gpu::Batch& batch, ViewFrustum& camera) {
// get the lock for the duration of the call
QMutexLocker locker(&_mutex);
@ -142,7 +133,7 @@ EnvironmentData Environment::getClosestData(const glm::vec3& position) {
// NOTE: Deprecated - I'm leaving this in for now, but it's not actually used. I made it private
// so that if anyone wants to start using this in the future they will consider how to make it
// so that if anyone wants to start using this in the future they will consider how to make it
// work with new physics systems.
glm::vec3 Environment::getGravity (const glm::vec3& position) {
//
@ -169,7 +160,7 @@ glm::vec3 Environment::getGravity (const glm::vec3& position) {
// At or inside a planet, gravity is as set for the planet
gravity += glm::normalize(vector) * environmentData.getGravity();
} else {
// Outside a planet, the gravity falls off with distance
// Outside a planet, the gravity falls off with distance
gravityStrength = 1.0f / powf(glm::length(vector) / surfaceRadius, 2.0f);
gravity += glm::normalize(vector) * environmentData.getGravity() * gravityStrength;
}
@ -205,33 +196,28 @@ bool Environment::findCapsulePenetration(const glm::vec3& start, const glm::vec3
return found;
}
int Environment::parseData(const HifiSockAddr& senderAddress, const QByteArray& packet) {
// push past the packet header
int bytesRead = numBytesForPacketHeader(packet);
int Environment::processPacket(NLPacket& packet) {
// push past flags, sequence, timestamp
bytesRead += sizeof(OCTREE_PACKET_FLAGS);
bytesRead += sizeof(OCTREE_PACKET_SEQUENCE);
bytesRead += sizeof(OCTREE_PACKET_SENT_TIME);
packet.seek(sizeof(OCTREE_PACKET_FLAGS) + sizeof(OCTREE_PACKET_SEQUENCE) + sizeof(OCTREE_PACKET_SENT_TIME));
// get the lock for the duration of the call
QMutexLocker locker(&_mutex);
EnvironmentData newData;
while (bytesRead < packet.size()) {
int dataLength = newData.parseData(reinterpret_cast<const unsigned char*>(packet.data()) + bytesRead,
packet.size() - bytesRead);
while (packet.bytesAvailable() > 0) {
int dataLength = newData.parseData(reinterpret_cast<const unsigned char*>(packet.getPayload() + packet.pos()),
packet.bytesAvailable());
packet.seek(packet.pos() + dataLength);
// update the mapping by address/ID
_data[senderAddress][newData.getID()] = newData;
bytesRead += dataLength;
_data[packet.getSourceID()][newData.getID()] = newData;
}
// remove the default mapping, if any
_data.remove(HifiSockAddr());
_data.remove(QUuid());
return bytesRead;
return packet.pos();
}
void Environment::renderAtmosphere(gpu::Batch& batch, ViewFrustum& camera, const EnvironmentData& data) {

View file

@ -36,13 +36,12 @@ public:
void endOverride() { _environmentIsOverridden = false; }
EnvironmentData getClosestData(const glm::vec3& position);
int parseData(const HifiSockAddr& senderSockAddr, const QByteArray& packet);
int processPacket(NLPacket& packet);
private:
glm::vec3 getGravity (const glm::vec3& position); // NOTE: Deprecated
bool findCapsulePenetration(const glm::vec3& start,
bool findCapsulePenetration(const glm::vec3& start,
const glm::vec3& end, float radius, glm::vec3& penetration); // NOTE: Deprecated
void renderAtmosphere(gpu::Batch& batch, ViewFrustum& camera, const EnvironmentData& data);
@ -79,7 +78,7 @@ private:
typedef QHash<int, EnvironmentData> ServerData;
QHash<HifiSockAddr, ServerData> _data;
QHash<QUuid, ServerData> _data;
EnvironmentData _overrideData;
bool _environmentIsOverridden = false;