Use the existing session stuff for metavoxels rather than a separate system.

This commit is contained in:
Andrzej Kapolka 2014-02-13 10:25:10 -08:00
parent bb56e2847f
commit 9c91d3c2e7
6 changed files with 69 additions and 167 deletions

View file

@ -28,15 +28,16 @@ void MetavoxelServer::applyEdit(const MetavoxelEditMessage& edit) {
edit.apply(_data);
}
void MetavoxelServer::removeSession(const QUuid& sessionId) {
_sessions.take(sessionId)->deleteLater();
}
const char METAVOXEL_SERVER_LOGGING_NAME[] = "metavoxel-server";
void MetavoxelServer::run() {
commonInit(METAVOXEL_SERVER_LOGGING_NAME, NodeType::MetavoxelServer);
NodeList* nodeList = NodeList::getInstance();
nodeList->addNodeTypeToInterestSet(NodeType::Agent);
connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), SLOT(maybeAttachSession(const SharedNodePointer&)));
_lastSend = QDateTime::currentMSecsSinceEpoch();
_sendTimer.start(SEND_INTERVAL);
}
@ -50,25 +51,31 @@ void MetavoxelServer::readPendingDatagrams() {
while (readAvailableDatagram(receivedPacket, senderSockAddr)) {
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
switch (packetTypeForPacket(receivedPacket)) {
case PacketTypeMetavoxelData: {
SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket);
if (matchingNode) {
processData(receivedPacket, matchingNode);
}
case PacketTypeMetavoxelData:
nodeList->findNodeAndUpdateWithDataFromPacket(receivedPacket);
break;
}
default:
NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket);
nodeList->processNodeData(senderSockAddr, receivedPacket);
break;
}
}
}
}
void MetavoxelServer::maybeAttachSession(const SharedNodePointer& node) {
if (node->getType() == NodeType::Agent) {
QMutexLocker locker(&node->getMutex());
node->setLinkedData(new MetavoxelSession(this, NodeList::getInstance()->nodeWithUUID(node->getUUID())));
}
}
void MetavoxelServer::sendDeltas() {
// send deltas for all sessions
foreach (MetavoxelSession* session, _sessions) {
session->sendDelta();
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
if (node->getType() == NodeType::Agent) {
static_cast<MetavoxelSession*>(node->getLinkedData())->sendDelta();
}
}
// restart the send timer
@ -79,35 +86,10 @@ void MetavoxelServer::sendDeltas() {
_sendTimer.start(qMax(0, 2 * SEND_INTERVAL - elapsed));
}
void MetavoxelServer::processData(const QByteArray& data, const SharedNodePointer& sendingNode) {
// read the session id
int headerPlusIDSize;
QUuid sessionID = readSessionID(data, sendingNode, headerPlusIDSize);
if (sessionID.isNull()) {
return;
}
// forward to session, creating if necessary
MetavoxelSession*& session = _sessions[sessionID];
if (!session) {
session = new MetavoxelSession(this, sessionID, QByteArray::fromRawData(data.constData(), headerPlusIDSize),
sendingNode);
}
session->receivedData(data, sendingNode);
}
MetavoxelSession::MetavoxelSession(MetavoxelServer* server, const QUuid& sessionId,
const QByteArray& datagramHeader, const SharedNodePointer& sendingNode) :
QObject(server),
MetavoxelSession::MetavoxelSession(MetavoxelServer* server, const SharedNodePointer& node) :
_server(server),
_sessionId(sessionId),
_sequencer(datagramHeader),
_sendingNode(sendingNode) {
const int TIMEOUT_INTERVAL = 30 * 1000;
_timeoutTimer.setInterval(TIMEOUT_INTERVAL);
_timeoutTimer.setSingleShot(true);
connect(&_timeoutTimer, SIGNAL(timeout()), SLOT(timedOut()));
_sequencer(byteArrayWithPopluatedHeader(PacketTypeMetavoxelData)),
_node(node) {
connect(&_sequencer, SIGNAL(readyToWrite(const QByteArray&)), SLOT(sendData(const QByteArray&)));
connect(&_sequencer, SIGNAL(readyToRead(Bitstream&)), SLOT(readPacket(Bitstream&)));
@ -117,19 +99,15 @@ MetavoxelSession::MetavoxelSession(MetavoxelServer* server, const QUuid& session
// insert the baseline send record
SendRecord record = { 0 };
_sendRecords.append(record);
qDebug() << "Opened session [sessionId=" << _sessionId << ", sendingNode=" << sendingNode << "]";
}
void MetavoxelSession::receivedData(const QByteArray& data, const SharedNodePointer& sendingNode) {
// reset the timeout timer
_timeoutTimer.start();
MetavoxelSession::~MetavoxelSession() {
}
// save the most recent sender
_sendingNode = sendingNode;
int MetavoxelSession::parseData(const QByteArray& packet) {
// process through sequencer
_sequencer.receivedDatagram(data);
_sequencer.receivedDatagram(packet);
return packet.size();
}
void MetavoxelSession::sendDelta() {
@ -143,13 +121,8 @@ void MetavoxelSession::sendDelta() {
_sendRecords.append(record);
}
void MetavoxelSession::timedOut() {
qDebug() << "Session timed out [sessionId=" << _sessionId << ", sendingNode=" << _sendingNode << "]";
_server->removeSession(_sessionId);
}
void MetavoxelSession::sendData(const QByteArray& data) {
NodeList::getInstance()->writeDatagram(data, _sendingNode);
NodeList::getInstance()->writeDatagram(data, _node);
}
void MetavoxelSession::readPacket(Bitstream& in) {
@ -164,11 +137,7 @@ void MetavoxelSession::clearSendRecordsBefore(int index) {
void MetavoxelSession::handleMessage(const QVariant& message) {
int userType = message.userType();
if (userType == CloseSessionMessage::Type) {
qDebug() << "Session closed [sessionId=" << _sessionId << ", sendingNode=" << _sendingNode << "]";
_server->removeSession(_sessionId);
} else if (userType == ClientStateMessage::Type) {
if (userType == ClientStateMessage::Type) {
ClientStateMessage state = message.value<ClientStateMessage>();
_position = state.position;

View file

@ -9,12 +9,9 @@
#ifndef __hifi__MetavoxelServer__
#define __hifi__MetavoxelServer__
#include <QHash>
#include <QList>
#include <QTimer>
#include <QUuid>
#include <HifiSockAddr.h>
#include <ThreadedAssignment.h>
#include <DatagramSequencer.h>
@ -35,45 +32,38 @@ public:
const MetavoxelData& getData() const { return _data; }
void removeSession(const QUuid& sessionId);
virtual void run();
virtual void readPendingDatagrams();
private slots:
void maybeAttachSession(const SharedNodePointer& node);
void sendDeltas();
private:
void processData(const QByteArray& data, const SharedNodePointer& sendingNode);
QTimer _sendTimer;
qint64 _lastSend;
QHash<QUuid, MetavoxelSession*> _sessions;
MetavoxelData _data;
};
/// Contains the state of a single client session.
class MetavoxelSession : public QObject {
class MetavoxelSession : public NodeData {
Q_OBJECT
public:
MetavoxelSession(MetavoxelServer* server, const QUuid& sessionId,
const QByteArray& datagramHeader, const SharedNodePointer& sendingNode);
MetavoxelSession(MetavoxelServer* server, const SharedNodePointer& node);
virtual ~MetavoxelSession();
void receivedData(const QByteArray& data, const SharedNodePointer& sendingNode);
virtual int parseData(const QByteArray& packet);
void sendDelta();
private slots:
void timedOut();
void sendData(const QByteArray& data);
void readPacket(Bitstream& in);
@ -91,12 +81,10 @@ private:
};
MetavoxelServer* _server;
QUuid _sessionId;
QTimer _timeoutTimer;
DatagramSequencer _sequencer;
SharedNodePointer _sendingNode;
SharedNodePointer _node;
glm::vec3 _position;

View file

@ -94,7 +94,7 @@ void DatagramProcessor::processDatagrams() {
break;
}
case PacketTypeMetavoxelData:
application->_metavoxels.processData(incomingPacket, senderSockAddr);
nodeList->findNodeAndUpdateWithDataFromPacket(incomingPacket);
break;
case PacketTypeBulkAvatarData:
case PacketTypeKillAvatar:

View file

@ -25,12 +25,6 @@ MetavoxelSystem::MetavoxelSystem() :
_buffer(QOpenGLBuffer::VertexBuffer) {
}
MetavoxelSystem::~MetavoxelSystem() {
for (QHash<QUuid, MetavoxelClient*>::const_iterator it = _clients.begin(); it != _clients.end(); it++) {
delete it.value();
}
}
void MetavoxelSystem::init() {
if (!_program.isLinked()) {
switchToResourcesParentIfRequired();
@ -42,33 +36,35 @@ void MetavoxelSystem::init() {
// let the script cache know to use our common access manager
ScriptCache::getInstance()->setNetworkAccessManager(Application::getInstance()->getNetworkAccessManager());
}
NodeList* nodeList = NodeList::getInstance();
connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), SLOT(nodeAdded(SharedNodePointer)));
connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer)));
_buffer.setUsagePattern(QOpenGLBuffer::DynamicDraw);
_buffer.create();
connect(NodeList::getInstance(), SIGNAL(nodeAdded(SharedNodePointer)), SLOT(maybeAttachClient(const SharedNodePointer&)));
}
void MetavoxelSystem::applyEdit(const MetavoxelEditMessage& edit) {
foreach (MetavoxelClient* client, _clients) {
client->applyEdit(edit);
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
if (node->getType() == NodeType::MetavoxelServer) {
MetavoxelClient* client = static_cast<MetavoxelClient*>(node->getLinkedData());
if (client) {
client->applyEdit(edit);
}
}
}
}
void MetavoxelSystem::processData(const QByteArray& data, const HifiSockAddr& sender) {
QMetaObject::invokeMethod(this, "receivedData", Q_ARG(const QByteArray&, data), Q_ARG(const HifiSockAddr&, sender));
}
void MetavoxelSystem::simulate(float deltaTime) {
// simulate the clients
_points.clear();
foreach (MetavoxelClient* client, _clients) {
client->simulate(deltaTime, _pointVisitor);
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
if (node->getType() == NodeType::MetavoxelServer) {
MetavoxelClient* client = static_cast<MetavoxelClient*>(node->getLinkedData());
if (client) {
client->simulate(deltaTime, _pointVisitor);
}
}
}
_buffer.bind();
int bytes = _points.size() * sizeof(Point);
if (_buffer.size() < bytes) {
@ -120,39 +116,10 @@ void MetavoxelSystem::render() {
_program.release();
}
void MetavoxelSystem::nodeAdded(SharedNodePointer node) {
void MetavoxelSystem::maybeAttachClient(const SharedNodePointer& node) {
if (node->getType() == NodeType::MetavoxelServer) {
QMetaObject::invokeMethod(this, "addClient", Q_ARG(const SharedNodePointer&, node));
}
}
void MetavoxelSystem::nodeKilled(SharedNodePointer node) {
if (node->getType() == NodeType::MetavoxelServer) {
QMetaObject::invokeMethod(this, "removeClient", Q_ARG(const QUuid&, node->getUUID()));
}
}
void MetavoxelSystem::addClient(const SharedNodePointer& node) {
MetavoxelClient* client = new MetavoxelClient(node);
_clients.insert(node->getUUID(), client);
_clientsBySessionID.insert(client->getSessionID(), client);
}
void MetavoxelSystem::removeClient(const QUuid& uuid) {
MetavoxelClient* client = _clients.take(uuid);
_clientsBySessionID.remove(client->getSessionID());
delete client;
}
void MetavoxelSystem::receivedData(const QByteArray& data, const SharedNodePointer& sendingNode) {
int headerPlusIDSize;
QUuid sessionID = readSessionID(data, sendingNode, headerPlusIDSize);
if (sessionID.isNull()) {
return;
}
MetavoxelClient* client = _clientsBySessionID.value(sessionID);
if (client) {
client->receivedData(data);
QMutexLocker locker(&node->getMutex());
node->setLinkedData(new MetavoxelClient(NodeList::getInstance()->nodeWithUUID(node->getUUID())));
}
}
@ -179,16 +146,9 @@ bool MetavoxelSystem::PointVisitor::visit(MetavoxelInfo& info) {
return false;
}
static QByteArray createDatagramHeader(const QUuid& sessionID) {
QByteArray header = byteArrayWithPopluatedHeader(PacketTypeMetavoxelData);
header += sessionID.toRfc4122();
return header;
}
MetavoxelClient::MetavoxelClient(const SharedNodePointer& node) :
_node(node),
_sessionID(QUuid::createUuid()),
_sequencer(createDatagramHeader(_sessionID)) {
_sequencer(byteArrayWithPopluatedHeader(PacketTypeMetavoxelData)) {
connect(&_sequencer, SIGNAL(readyToWrite(const QByteArray&)), SLOT(sendData(const QByteArray&)));
connect(&_sequencer, SIGNAL(readyToRead(Bitstream&)), SLOT(readPacket(Bitstream&)));
@ -223,9 +183,10 @@ void MetavoxelClient::simulate(float deltaTime, MetavoxelVisitor& visitor) {
_data.guide(visitor);
}
void MetavoxelClient::receivedData(const QByteArray& data) {
int MetavoxelClient::parseData(const QByteArray& packet) {
// process through sequencer
_sequencer.receivedDatagram(data);
QMetaObject::invokeMethod(&_sequencer, "receivedDatagram", Q_ARG(const QByteArray&, packet));
return packet.size();
}
void MetavoxelClient::sendData(const QByteArray& data) {

View file

@ -23,8 +23,6 @@
#include "renderer/ProgramObject.h"
class MetavoxelClient;
/// Renders a metavoxel tree.
class MetavoxelSystem : public QObject {
Q_OBJECT
@ -32,28 +30,20 @@ class MetavoxelSystem : public QObject {
public:
MetavoxelSystem();
~MetavoxelSystem();
void init();
void applyEdit(const MetavoxelEditMessage& edit);
void processData(const QByteArray& data, const HifiSockAddr& sender);
void simulate(float deltaTime);
void render();
public slots:
private slots:
void maybeAttachClient(const SharedNodePointer& node);
void nodeAdded(SharedNodePointer node);
void nodeKilled(SharedNodePointer node);
private:
Q_INVOKABLE void addClient(const SharedNodePointer& node);
Q_INVOKABLE void removeClient(const QUuid& uuid);
Q_INVOKABLE void receivedData(const QByteArray& data, const SharedNodePointer& sendingNode);
class Point {
public:
glm::vec4 vertex;
@ -76,13 +66,10 @@ private:
QVector<Point> _points;
PointVisitor _pointVisitor;
QOpenGLBuffer _buffer;
QHash<QUuid, MetavoxelClient*> _clients;
QHash<QUuid, MetavoxelClient*> _clientsBySessionID;
};
/// A client session associated with a single server.
class MetavoxelClient : public QObject {
class MetavoxelClient : public NodeData {
Q_OBJECT
public:
@ -90,13 +77,11 @@ public:
MetavoxelClient(const SharedNodePointer& node);
virtual ~MetavoxelClient();
const QUuid& getSessionID() const { return _sessionID; }
void applyEdit(const MetavoxelEditMessage& edit);
void simulate(float deltaTime, MetavoxelVisitor& visitor);
void receivedData(const QByteArray& data);
virtual int parseData(const QByteArray& packet);
private slots:
@ -117,7 +102,6 @@ private:
};
SharedNodePointer _node;
QUuid _sessionID;
DatagramSequencer _sequencer;

View file

@ -70,7 +70,7 @@ public:
/// Processes a datagram received from the other party, emitting readyToRead when the entire packet
/// has been successfully assembled.
void receivedDatagram(const QByteArray& datagram);
Q_INVOKABLE void receivedDatagram(const QByteArray& datagram);
signals: