Merge branch 'atp' of https://github.com/birarda/hifi into protocol

This commit is contained in:
Atlante45 2015-07-06 16:40:47 -07:00
commit 0c7dc1e28f
5 changed files with 193 additions and 40 deletions

View file

@ -927,15 +927,22 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
const NodeSet& nodeInterestSet) {
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
auto listPacket = NodeListPacket::make(PacketType::DomainList);
PacketList domainListPackets(PacketType::DomainList);
// always send the node their own UUID back
QDataStream broadcastDataStream(&listPacket.payload(), QIODevice::Append);
broadcastDataStream << node->getUUID();
broadcastDataStream << node->getCanAdjustLocks();
broadcastDataStream << node->getCanRez();
QDataStream domainListStream(&domainListPackets);
int numBroadcastPacketLeadBytes = broadcastDataStream.device()->pos();
const int NUM_DOMAIN_LIST_EXTENDED_HEADER_BYTES = NUM_BYTES_RFC4122_UUID + 2;
// setup the extended header for the domain list packets
// this data is at the beginning of each of the domain list packets
QByteArray extendedHeader(NUM_DOMAIN_LIST_EXTENDED_HEADER_BYTES, 0);
extendedHeader.replace(0, NUM_BYTES_RFC4122_UUID, node->getUUID().toRfc4122());
extendedHeader[NUM_BYTES_RFC4122_UUID] = (char) node->getCanAdjustLocks();
extendedHeader[NUM_BYTES_RFC4122_UUID + 1] = (char) node->getCanRez();
domainListPackets.setExtendedHeader(extendedHeader);
DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(node->getLinkedData());
@ -944,44 +951,29 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
if (nodeInterestSet.size() > 0) {
// DTLSServerSession* dtlsSession = _isUsingDTLS ? _dtlsSessions[senderSockAddr] : NULL;
int dataMTU = MAX_PACKET_SIZE;
// DTLSServerSession* dtlsSession = _isUsingDTLS ? _dtlsSessions[senderSockAddr] : NULL;
if (nodeData->isAuthenticated()) {
// if this authenticated node has any interest types, send back those nodes as well
limitedNodeList->eachNode([&](const SharedNodePointer& otherNode){
// reset our nodeByteArray and nodeDataStream
QByteArray nodeByteArray;
QDataStream nodeDataStream(&nodeByteArray, QIODevice::Append);
if (otherNode->getUUID() != node->getUUID() && nodeInterestSet.contains(otherNode->getType())) {
// since we're about to add a node to the packet we start a segment
domainListStream.startSegment();
// don't send avatar nodes to other avatars, that will come from avatar mixer
nodeDataStream << *otherNode.data();
domainListStream << *otherNode.data();
// pack the secret that these two nodes will use to communicate with each other
nodeDataStream << connectionSecretForNodes(node, otherNode);
domainListStream << connectionSecretForNodes(node, otherNode);
if (broadcastPacket.size() + nodeByteArray.size() > dataMTU) {
// we need to break here and start a new packet
// so send the current one
limitedNodeList->writeUnverifiedDatagram(broadcastPacket, node, senderSockAddr);
// reset the broadcastPacket structure
broadcastPacket.resize(numBroadcastPacketLeadBytes);
broadcastDataStream.device()->seek(numBroadcastPacketLeadBytes);
}
// append the nodeByteArray to the current state of broadcastDataStream
broadcastPacket.append(nodeByteArray);
// we've added the node we wanted so end the segment now
domainListStream.endSegment();
}
});
}
}
// always write the last broadcastPacket
limitedNodeList->writeUnverifiedDatagram(broadcastPacket, node);
// write the PacketList to this node
limitedNodeList->sendPacketList(domainListPackets, node);
}
QUuid DomainServer::connectionSecretForNodes(const SharedNodePointer& nodeA, const SharedNodePointer& nodeB) {

View file

@ -0,0 +1,111 @@
//
// PacketList.cpp
// libraries/networking/src
//
// Created by Stephen Birarda on 07/06/15.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "PacketList.h"
PacketList::PacketList(PacketType::Value packetType, bool isOrdered) :
_packetType(packetType),
_isOrdered(isOrdered)
{
}
void PacketList::createPacketWithExtendedHeader() {
// use the static create method to create a new packet
_currentPacket = T::create(_packetType);
// add the extended header to the front of the packet
if (_currentPacket.write(_extendedHeader) == -1) {
qDebug() << "Could not write extendedHeader in PacketList::createPacketWithExtendedHeader"
<< "- make sure that _extendedHeader is not larger than the payload capacity.";
}
}
qint64 writeData(const char* data, qint64 maxSize) {
if (!_currentPacket) {
// we don't have a current packet, time to set one up
createPacketWithExtendedHeader();
}
// check if this block of data can fit into the currentPacket
if (maxSize <= _currentPacket.size()) {
// it fits, just write it to the current packet
_currentPacket.write(data, maxSize);
// return the number of bytes written
return maxSize;
} else {
// it does not fit - this may need to be in the next packet
if (!_isOrdered) {
auto newPacket = T::create(_packetType);
PacketPayload& newPayload = newPacket.getPayload();
if (_segmentStartIndex >= 0) {
// We in the process of writing a segment for an unordered PacketList.
// We need to try and pull the first part of the segment out to our new packet
PacketPayload& currentPayload = _currentPacket->getPayload();
// check now to see if this is an unsupported write
int numBytesToEnd = currentPayload.size() - _segmentStartIndex;
if ((newPayload.size() - numBytesToEnd) < maxSize) {
// this is an unsupported case - the segment is bigger than the size of an individual packet
// but the PacketList is not going to be sent ordered
qDebug() << "Error in PacketList::writeData - attempted to write a segment to an unordered packet that is"
<< "larger than the payload size.";
return -1;
}
// copy from currentPacket where the segment started to the beginning of the newPacket
newPayload.write(currentPacket.constData() + _segmentStartIndex, numBytesToEnd);
// the current segment now starts at the beginning of the new packet
_segmentStartIndex = 0;
// shrink the current payload to the actual size of the packet
currentPayload.setSizeUsed(_segmentStartIndex);
}
// move the current packet to our list of packets
_packets.insert(std::move(_currentPacket));
// write the data to the newPacket
newPayload.write(data, maxSize);
// set our current packet to the new packet
_currentPacket = newPacket;
// return the number of bytes written to the new packet
return maxSize;
} else {
// we're an ordered PacketList - let's fit what we can into the current packet and then put the leftover
// into a new packet
PacketPayload& currentPayload = _currentPacket.getPayload();
int numBytesToEnd = _currentPayload.size() - _currentPayload.pos();
_currentPacket.write(data, numBytesToEnd);
// move the current packet to our list of packets
_packets.insert(std::move(_currentPacket));
// recursively call our writeData method for the remaining data to write to a new packet
return numBytesToEnd + writeData(data + numBytesToEnd, maxSize - numBytesToEnd);
}
}
}
void PacketList::closeCurrentPacket() {
// move the current packet to our list of packets
_packets.insert(std::move(_currentPacket));
}

View file

@ -0,0 +1,46 @@
//
// PacketList.h
// libraries/networking/src
//
// Created by Stephen Birarda on 07/06/15.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_PacketList_h
#define hifi_PacketList_h
#pragma once
template <class T> class PacketList : public QIODevice {
public:
PacketList(PacketType::Value packetType, bool isOrdered = false);
virtual bool isSequential() const { return true; }
void startSegment() { _segmentStartIndex = currentPacket->payload().pos(); }
void endSegment() { _segmentStartIndex = -1; }
void closeCurrentPacket();
void setExtendedHeader(const QByteArray& extendedHeader) { _extendedHeader = extendedHeader; }
protected:
qint64 writeData(const char* data, qint64 maxSize);
qint64 readData(const char* data, qint64 maxSize) { return 0 };
private:
void createPacketWithExtendedHeader();
PacketType::Value _packetType;
bool isOrdered;
std::unique_ptr<T> _currentPacket;
std::list<std::unique_ptr<T>> _packets;
int _segmentStartIndex = -1;
QByteArray _extendedHeader = extendedHeader;
}
#endif // hifi_PacketList_h

View file

@ -11,9 +11,9 @@
#include "PacketPayload.h"
PacketPayload::PacketPayload(char* data, qint64 size) :
PacketPayload::PacketPayload(char* data, qint64 capacity) :
_data(data)
_size(size)
_capacity(capacity)
{
}
@ -25,7 +25,7 @@ qint64 PacketPayload::writeData(const char* data, qint64 maxSize) {
qint64 currentPos = pos();
// make sure we have the space required to write this block
qint64 bytesAvailable = _size - currentPos;
qint64 bytesAvailable = _capacity - currentPos;
if (bytesAvailable < srcBytes) {
// good to go - write the data
@ -35,7 +35,7 @@ qint64 PacketPayload::writeData(const char* data, qint64 maxSize) {
seek(currentPos + srcBytes);
// keep track of _maxWritten so we can just write the actual data when packet is about to be sent
_maxWritten = std::max(pos() + 1, _maxWritten);
_size = std::max(pos() + 1, _maxWritten);
// return the number of bytes written
return srcBytes;

View file

@ -18,19 +18,23 @@
class PacketPayload : public QIODevice {
public:
PacketPayload(char* data, qint64 size);
PacketPayload(char* data, qint64 capacity);
virtual qint64 size() const { return _size; }
qint64 getSizeUsed() const { return _sizeUsed; }
void setSizeUsed(qint64 sizeUsed) { _sizeUsed = sizeUsed; }
virtual qint64 size() const { return _capacity; }
virtual bool isSequential() const { return false; }
const char* constData() const { return _data; }
protected:
virtual qint64 writeData(const char* data, qint64 maxSize);
virtual qint64 readData(const char* data, qint64 maxSize);
qint64 writeData(const char* data, qint64 maxSize);
qint64 readData(char* data, qint64 maxSize);
private:
char* _data;
qint64 _size = 0;
qint64 _maxWritten = 0;
qint64 _sizeUsed = 0;
qint64 _capacity = 0;
};
#endif // hifi_PacketPayload_h