final fixes for path query from DS

This commit is contained in:
Stephen Birarda 2015-05-12 14:34:14 -07:00
parent 7330e5255d
commit 332601b91c
9 changed files with 153 additions and 91 deletions

View file

@ -2255,8 +2255,8 @@ void DomainServer::respondToPathQuery(const QByteArray& receivedPacket, const Hi
qDebug() << "Sending a viewpoint response for path query" << pathQuery << "-" << viewpointUTF8; qDebug() << "Sending a viewpoint response for path query" << pathQuery << "-" << viewpointUTF8;
// send off the packet - see if we can associate this outbound data to a particular node // send off the packet - see if we can associate this outbound data to a particular node
SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket); // TODO: does this senderSockAddr always work for a punched DS client?
nodeList->writeUnverifiedDatagram(pathResponsePacket, matchingNode, senderSockAddr); nodeList->writeUnverifiedDatagram(pathResponsePacket, senderSockAddr);
} }
} }

View file

@ -25,7 +25,7 @@
DatagramProcessor::DatagramProcessor(QObject* parent) : DatagramProcessor::DatagramProcessor(QObject* parent) :
QObject(parent) QObject(parent)
{ {
} }
void DatagramProcessor::processDatagrams() { void DatagramProcessor::processDatagrams() {
@ -35,23 +35,23 @@ void DatagramProcessor::processDatagrams() {
if (_isShuttingDown) { if (_isShuttingDown) {
return; // bail early... we're shutting down. return; // bail early... we're shutting down.
} }
HifiSockAddr senderSockAddr; HifiSockAddr senderSockAddr;
static QByteArray incomingPacket; static QByteArray incomingPacket;
Application* application = Application::getInstance(); Application* application = Application::getInstance();
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
while (DependencyManager::get<NodeList>()->getNodeSocket().hasPendingDatagrams()) { while (DependencyManager::get<NodeList>()->getNodeSocket().hasPendingDatagrams()) {
incomingPacket.resize(nodeList->getNodeSocket().pendingDatagramSize()); incomingPacket.resize(nodeList->getNodeSocket().pendingDatagramSize());
nodeList->readDatagram(incomingPacket, senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer()); nodeList->readDatagram(incomingPacket, senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer());
_inPacketCount++; _inPacketCount++;
_inByteCount += incomingPacket.size(); _inByteCount += incomingPacket.size();
if (nodeList->packetVersionAndHashMatch(incomingPacket)) { if (nodeList->packetVersionAndHashMatch(incomingPacket)) {
PacketType incomingType = packetTypeForPacket(incomingPacket); PacketType incomingType = packetTypeForPacket(incomingPacket);
// only process this packet if we have a match on the packet version // only process this packet if we have a match on the packet version
switch (incomingType) { switch (incomingType) {
@ -72,14 +72,14 @@ void DatagramProcessor::processDatagrams() {
Qt::QueuedConnection, Qt::QueuedConnection,
Q_ARG(QByteArray, incomingPacket)); Q_ARG(QByteArray, incomingPacket));
} }
// update having heard from the audio-mixer and record the bytes received // update having heard from the audio-mixer and record the bytes received
SharedNodePointer audioMixer = nodeList->sendingNodeForPacket(incomingPacket); SharedNodePointer audioMixer = nodeList->sendingNodeForPacket(incomingPacket);
if (audioMixer) { if (audioMixer) {
audioMixer->setLastHeardMicrostamp(usecTimestampNow()); audioMixer->setLastHeardMicrostamp(usecTimestampNow());
} }
break; break;
} }
case PacketTypeEntityAddResponse: case PacketTypeEntityAddResponse:
@ -94,7 +94,7 @@ void DatagramProcessor::processDatagrams() {
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
"Application::networkReceive()... _octreeProcessor.queueReceivedPacket()"); "Application::networkReceive()... _octreeProcessor.queueReceivedPacket()");
SharedNodePointer matchedNode = DependencyManager::get<NodeList>()->sendingNodeForPacket(incomingPacket); SharedNodePointer matchedNode = DependencyManager::get<NodeList>()->sendingNodeForPacket(incomingPacket);
if (matchedNode) { if (matchedNode) {
// add this packet to our list of octree packets and process them on the octree data processing // add this packet to our list of octree packets and process them on the octree data processing
application->_octreeProcessor.queueReceivedPacket(matchedNode, incomingPacket); application->_octreeProcessor.queueReceivedPacket(matchedNode, incomingPacket);
@ -107,10 +107,10 @@ void DatagramProcessor::processDatagrams() {
case PacketTypeAvatarBillboard: { case PacketTypeAvatarBillboard: {
// update having heard from the avatar-mixer and record the bytes received // update having heard from the avatar-mixer and record the bytes received
SharedNodePointer avatarMixer = nodeList->sendingNodeForPacket(incomingPacket); SharedNodePointer avatarMixer = nodeList->sendingNodeForPacket(incomingPacket);
if (avatarMixer) { if (avatarMixer) {
avatarMixer->setLastHeardMicrostamp(usecTimestampNow()); avatarMixer->setLastHeardMicrostamp(usecTimestampNow());
QMetaObject::invokeMethod(DependencyManager::get<AvatarManager>().data(), "processAvatarMixerDatagram", QMetaObject::invokeMethod(DependencyManager::get<AvatarManager>().data(), "processAvatarMixerDatagram",
Q_ARG(const QByteArray&, incomingPacket), Q_ARG(const QByteArray&, incomingPacket),
Q_ARG(const QWeakPointer<Node>&, avatarMixer)); Q_ARG(const QWeakPointer<Node>&, avatarMixer));
@ -135,20 +135,20 @@ void DatagramProcessor::processDatagrams() {
case PacketTypeNoisyMute: case PacketTypeNoisyMute:
case PacketTypeMuteEnvironment: { case PacketTypeMuteEnvironment: {
bool mute = !DependencyManager::get<AudioClient>()->isMuted(); bool mute = !DependencyManager::get<AudioClient>()->isMuted();
if (incomingType == PacketTypeMuteEnvironment) { if (incomingType == PacketTypeMuteEnvironment) {
glm::vec3 position; glm::vec3 position;
float radius; float radius;
int headerSize = numBytesForPacketHeaderGivenPacketType(PacketTypeMuteEnvironment); int headerSize = numBytesForPacketHeaderGivenPacketType(PacketTypeMuteEnvironment);
memcpy(&position, incomingPacket.constData() + headerSize, sizeof(glm::vec3)); memcpy(&position, incomingPacket.constData() + headerSize, sizeof(glm::vec3));
memcpy(&radius, incomingPacket.constData() + headerSize + sizeof(glm::vec3), sizeof(float)); memcpy(&radius, incomingPacket.constData() + headerSize + sizeof(glm::vec3), sizeof(float));
float distance = glm::distance(DependencyManager::get<AvatarManager>()->getMyAvatar()->getPosition(), float distance = glm::distance(DependencyManager::get<AvatarManager>()->getMyAvatar()->getPosition(),
position); position);
mute = mute && (distance < radius); mute = mute && (distance < radius);
} }
if (mute) { if (mute) {
DependencyManager::get<AudioClient>()->toggleMute(); DependencyManager::get<AudioClient>()->toggleMute();
if (incomingType == PacketTypeMuteEnvironment) { if (incomingType == PacketTypeMuteEnvironment) {

View file

@ -125,7 +125,6 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl) {
// wasn't an address - lookup the place name // wasn't an address - lookup the place name
// we may have a path that defines a relative viewpoint - pass that through the lookup so we can go to it after // we may have a path that defines a relative viewpoint - pass that through the lookup so we can go to it after
attemptPlaceNameLookup(lookupUrl.host(), lookupUrl.path()); attemptPlaceNameLookup(lookupUrl.host(), lookupUrl.path());
} }
} }
@ -253,10 +252,13 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const
qCDebug(networking) << "Received a location path that was could not be handled as a viewpoint -" qCDebug(networking) << "Received a location path that was could not be handled as a viewpoint -"
<< returnedPath; << returnedPath;
} }
} else {
// we didn't override the path or get one back - ask the DS for the viewpoint of its index path
// which we will jump to if it exists
emit pathChangeRequired(INDEX_PATH);
} }
} }
} else { } else {
qCDebug(networking) << "Received an address manager API response with no domain key. Cannot parse."; qCDebug(networking) << "Received an address manager API response with no domain key. Cannot parse.";
qCDebug(networking) << locationMap; qCDebug(networking) << locationMap;

View file

@ -24,6 +24,7 @@
const QString HIFI_URL_SCHEME = "hifi"; const QString HIFI_URL_SCHEME = "hifi";
const QString DEFAULT_HIFI_ADDRESS = "hifi://entry"; const QString DEFAULT_HIFI_ADDRESS = "hifi://entry";
const QString INDEX_PATH = "/";
typedef const glm::vec3& (*PositionGetter)(); typedef const glm::vec3& (*PositionGetter)();
typedef glm::quat (*OrientationGetter)(); typedef glm::quat (*OrientationGetter)();

View file

@ -36,19 +36,19 @@ DomainHandler::DomainHandler(QObject* parent) :
_settingsObject(), _settingsObject(),
_failedSettingsRequests(0) _failedSettingsRequests(0)
{ {
} }
void DomainHandler::clearConnectionInfo() { void DomainHandler::clearConnectionInfo() {
_uuid = QUuid(); _uuid = QUuid();
_icePeer = NetworkPeer(); _icePeer = NetworkPeer();
if (requiresICE()) { if (requiresICE()) {
// if we connected to this domain with ICE, re-set the socket so we reconnect through the ice-server // if we connected to this domain with ICE, re-set the socket so we reconnect through the ice-server
_sockAddr.setAddress(QHostAddress::Null); _sockAddr.clear();
} }
setIsConnected(false); setIsConnected(false);
} }
@ -65,12 +65,15 @@ void DomainHandler::softReset() {
void DomainHandler::hardReset() { void DomainHandler::hardReset() {
softReset(); softReset();
qCDebug(networking) << "Hard reset in NodeList DomainHandler."; qCDebug(networking) << "Hard reset in NodeList DomainHandler.";
_iceDomainID = QUuid(); _iceDomainID = QUuid();
_iceServerSockAddr = HifiSockAddr(); _iceServerSockAddr = HifiSockAddr();
_hostname = QString(); _hostname = QString();
_sockAddr.setAddress(QHostAddress::Null); _sockAddr.clear();
// clear any pending path we may have wanted to ask the previous DS about
_pendingPath.clear();
} }
void DomainHandler::setSockAddr(const HifiSockAddr& sockAddr, const QString& hostname) { void DomainHandler::setSockAddr(const HifiSockAddr& sockAddr, const QString& hostname) {
@ -80,7 +83,7 @@ void DomainHandler::setSockAddr(const HifiSockAddr& sockAddr, const QString& hos
// change the sockAddr // change the sockAddr
_sockAddr = sockAddr; _sockAddr = sockAddr;
} }
// some callers may pass a hostname, this is not to be used for lookup but for DTLS certificate verification // some callers may pass a hostname, this is not to be used for lookup but for DTLS certificate verification
_hostname = hostname; _hostname = hostname;
} }
@ -93,29 +96,29 @@ void DomainHandler::setUUID(const QUuid& uuid) {
} }
void DomainHandler::setHostnameAndPort(const QString& hostname, quint16 port) { void DomainHandler::setHostnameAndPort(const QString& hostname, quint16 port) {
if (hostname != _hostname || _sockAddr.getPort() != port) { if (hostname != _hostname || _sockAddr.getPort() != port) {
// re-set the domain info so that auth information is reloaded // re-set the domain info so that auth information is reloaded
hardReset(); hardReset();
if (hostname != _hostname) { if (hostname != _hostname) {
// set the new hostname // set the new hostname
_hostname = hostname; _hostname = hostname;
qCDebug(networking) << "Updated domain hostname to" << _hostname; qCDebug(networking) << "Updated domain hostname to" << _hostname;
// re-set the sock addr to null and fire off a lookup of the IP address for this domain-server's hostname // re-set the sock addr to null and fire off a lookup of the IP address for this domain-server's hostname
qCDebug(networking, "Looking up DS hostname %s.", _hostname.toLocal8Bit().constData()); qCDebug(networking, "Looking up DS hostname %s.", _hostname.toLocal8Bit().constData());
QHostInfo::lookupHost(_hostname, this, SLOT(completedHostnameLookup(const QHostInfo&))); QHostInfo::lookupHost(_hostname, this, SLOT(completedHostnameLookup(const QHostInfo&)));
UserActivityLogger::getInstance().changedDomain(_hostname); UserActivityLogger::getInstance().changedDomain(_hostname);
emit hostnameChanged(_hostname); emit hostnameChanged(_hostname);
} }
if (_sockAddr.getPort() != port) { if (_sockAddr.getPort() != port) {
qCDebug(networking) << "Updated domain port to" << port; qCDebug(networking) << "Updated domain port to" << port;
} }
// grab the port by reading the string after the colon // grab the port by reading the string after the colon
_sockAddr.setPort(port); _sockAddr.setPort(port);
} }
@ -125,16 +128,16 @@ void DomainHandler::setIceServerHostnameAndID(const QString& iceServerHostname,
if (id != _uuid) { if (id != _uuid) {
// re-set the domain info to connect to new domain // re-set the domain info to connect to new domain
hardReset(); hardReset();
_iceDomainID = id; _iceDomainID = id;
HifiSockAddr* replaceableSockAddr = &_iceServerSockAddr; HifiSockAddr* replaceableSockAddr = &_iceServerSockAddr;
replaceableSockAddr->~HifiSockAddr(); replaceableSockAddr->~HifiSockAddr();
replaceableSockAddr = new (replaceableSockAddr) HifiSockAddr(iceServerHostname, ICE_SERVER_DEFAULT_PORT); replaceableSockAddr = new (replaceableSockAddr) HifiSockAddr(iceServerHostname, ICE_SERVER_DEFAULT_PORT);
// refresh our ICE client UUID to something new // refresh our ICE client UUID to something new
_iceClientID = QUuid::createUuid(); _iceClientID = QUuid::createUuid();
qCDebug(networking) << "ICE required to connect to domain via ice server at" << iceServerHostname; qCDebug(networking) << "ICE required to connect to domain via ice server at" << iceServerHostname;
} }
} }
@ -142,23 +145,29 @@ void DomainHandler::setIceServerHostnameAndID(const QString& iceServerHostname,
void DomainHandler::activateICELocalSocket() { void DomainHandler::activateICELocalSocket() {
_sockAddr = _icePeer.getLocalSocket(); _sockAddr = _icePeer.getLocalSocket();
_hostname = _sockAddr.getAddress().toString(); _hostname = _sockAddr.getAddress().toString();
emit completedSocketDiscovery();
} }
void DomainHandler::activateICEPublicSocket() { void DomainHandler::activateICEPublicSocket() {
_sockAddr = _icePeer.getPublicSocket(); _sockAddr = _icePeer.getPublicSocket();
_hostname = _sockAddr.getAddress().toString(); _hostname = _sockAddr.getAddress().toString();
emit completedSocketDiscovery();
} }
void DomainHandler::completedHostnameLookup(const QHostInfo& hostInfo) { void DomainHandler::completedHostnameLookup(const QHostInfo& hostInfo) {
for (int i = 0; i < hostInfo.addresses().size(); i++) { for (int i = 0; i < hostInfo.addresses().size(); i++) {
if (hostInfo.addresses()[i].protocol() == QAbstractSocket::IPv4Protocol) { if (hostInfo.addresses()[i].protocol() == QAbstractSocket::IPv4Protocol) {
_sockAddr.setAddress(hostInfo.addresses()[i]); _sockAddr.setAddress(hostInfo.addresses()[i]);
qCDebug(networking, "DS at %s is at %s", _hostname.toLocal8Bit().constData(), qCDebug(networking, "DS at %s is at %s", _hostname.toLocal8Bit().constData(),
_sockAddr.getAddress().toString().toLocal8Bit().constData()); _sockAddr.getAddress().toString().toLocal8Bit().constData());
emit completedSocketDiscovery();
return; return;
} }
} }
// if we got here then we failed to lookup the address // if we got here then we failed to lookup the address
qCDebug(networking, "Failed domain server lookup"); qCDebug(networking, "Failed domain server lookup");
} }
@ -166,10 +175,10 @@ void DomainHandler::completedHostnameLookup(const QHostInfo& hostInfo) {
void DomainHandler::setIsConnected(bool isConnected) { void DomainHandler::setIsConnected(bool isConnected) {
if (_isConnected != isConnected) { if (_isConnected != isConnected) {
_isConnected = isConnected; _isConnected = isConnected;
if (_isConnected) { if (_isConnected) {
emit connectedToDomain(_hostname); emit connectedToDomain(_hostname);
// we've connected to new domain - time to ask it for global settings // we've connected to new domain - time to ask it for global settings
requestDomainSettings(); requestDomainSettings();
} else { } else {
@ -195,9 +204,9 @@ void DomainHandler::requestDomainSettings() {
settingsJSONURL.setPath("/settings.json"); settingsJSONURL.setPath("/settings.json");
Assignment::Type assignmentType = Assignment::typeForNodeType(DependencyManager::get<NodeList>()->getOwnerType()); Assignment::Type assignmentType = Assignment::typeForNodeType(DependencyManager::get<NodeList>()->getOwnerType());
settingsJSONURL.setQuery(QString("type=%1").arg(assignmentType)); settingsJSONURL.setQuery(QString("type=%1").arg(assignmentType));
qCDebug(networking) << "Requesting domain-server settings at" << settingsJSONURL.toString(); qCDebug(networking) << "Requesting domain-server settings at" << settingsJSONURL.toString();
QNetworkRequest settingsRequest(settingsJSONURL); QNetworkRequest settingsRequest(settingsJSONURL);
settingsRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); settingsRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
QNetworkReply* reply = NetworkAccessManager::getInstance().get(settingsRequest); QNetworkReply* reply = NetworkAccessManager::getInstance().get(settingsRequest);
@ -210,23 +219,23 @@ const int MAX_SETTINGS_REQUEST_FAILED_ATTEMPTS = 5;
void DomainHandler::settingsRequestFinished() { void DomainHandler::settingsRequestFinished() {
QNetworkReply* settingsReply = reinterpret_cast<QNetworkReply*>(sender()); QNetworkReply* settingsReply = reinterpret_cast<QNetworkReply*>(sender());
int replyCode = settingsReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); int replyCode = settingsReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (settingsReply->error() == QNetworkReply::NoError && replyCode != 301 && replyCode != 302) { if (settingsReply->error() == QNetworkReply::NoError && replyCode != 301 && replyCode != 302) {
// parse the JSON to a QJsonObject and save it // parse the JSON to a QJsonObject and save it
_settingsObject = QJsonDocument::fromJson(settingsReply->readAll()).object(); _settingsObject = QJsonDocument::fromJson(settingsReply->readAll()).object();
qCDebug(networking) << "Received domain settings."; qCDebug(networking) << "Received domain settings.";
emit settingsReceived(_settingsObject); emit settingsReceived(_settingsObject);
// reset failed settings requests to 0, we got them // reset failed settings requests to 0, we got them
_failedSettingsRequests = 0; _failedSettingsRequests = 0;
} else { } else {
// error grabbing the settings - in some cases this means we are stuck // error grabbing the settings - in some cases this means we are stuck
// so we should retry until we get it // so we should retry until we get it
qCDebug(networking) << "Error getting domain settings -" << settingsReply->errorString() << "- retrying"; qCDebug(networking) << "Error getting domain settings -" << settingsReply->errorString() << "- retrying";
if (++_failedSettingsRequests >= MAX_SETTINGS_REQUEST_FAILED_ATTEMPTS) { if (++_failedSettingsRequests >= MAX_SETTINGS_REQUEST_FAILED_ATTEMPTS) {
qCDebug(networking) << "Failed to retreive domain-server settings" << MAX_SETTINGS_REQUEST_FAILED_ATTEMPTS qCDebug(networking) << "Failed to retreive domain-server settings" << MAX_SETTINGS_REQUEST_FAILED_ATTEMPTS
<< "times. Re-setting connection to domain."; << "times. Re-setting connection to domain.";
@ -235,7 +244,7 @@ void DomainHandler::settingsRequestFinished() {
emit settingsReceiveFail(); emit settingsReceiveFail();
} else { } else {
requestDomainSettings(); requestDomainSettings();
} }
} }
settingsReply->deleteLater(); settingsReply->deleteLater();
} }
@ -243,30 +252,30 @@ void DomainHandler::settingsRequestFinished() {
void DomainHandler::parseDTLSRequirementPacket(const QByteArray& dtlsRequirementPacket) { void DomainHandler::parseDTLSRequirementPacket(const QByteArray& dtlsRequirementPacket) {
// figure out the port that the DS wants us to use for us to talk to them with DTLS // figure out the port that the DS wants us to use for us to talk to them with DTLS
int numBytesPacketHeader = numBytesForPacketHeader(dtlsRequirementPacket); int numBytesPacketHeader = numBytesForPacketHeader(dtlsRequirementPacket);
unsigned short dtlsPort = 0; unsigned short dtlsPort = 0;
memcpy(&dtlsPort, dtlsRequirementPacket.data() + numBytesPacketHeader, sizeof(dtlsPort)); memcpy(&dtlsPort, dtlsRequirementPacket.data() + numBytesPacketHeader, sizeof(dtlsPort));
qCDebug(networking) << "domain-server DTLS port changed to" << dtlsPort << "- Enabling DTLS."; qCDebug(networking) << "domain-server DTLS port changed to" << dtlsPort << "- Enabling DTLS.";
_sockAddr.setPort(dtlsPort); _sockAddr.setPort(dtlsPort);
// initializeDTLSSession(); // initializeDTLSSession();
} }
void DomainHandler::processICEResponsePacket(const QByteArray& icePacket) { void DomainHandler::processICEResponsePacket(const QByteArray& icePacket) {
QDataStream iceResponseStream(icePacket); QDataStream iceResponseStream(icePacket);
iceResponseStream.skipRawData(numBytesForPacketHeader(icePacket)); iceResponseStream.skipRawData(numBytesForPacketHeader(icePacket));
NetworkPeer packetPeer; NetworkPeer packetPeer;
iceResponseStream >> packetPeer; iceResponseStream >> packetPeer;
if (packetPeer.getUUID() != _iceDomainID) { if (packetPeer.getUUID() != _iceDomainID) {
qCDebug(networking) << "Received a network peer with ID that does not match current domain. Will not attempt connection."; qCDebug(networking) << "Received a network peer with ID that does not match current domain. Will not attempt connection.";
} else { } else {
qCDebug(networking) << "Received network peer object for domain -" << packetPeer; qCDebug(networking) << "Received network peer object for domain -" << packetPeer;
_icePeer = packetPeer; _icePeer = packetPeer;
emit requestICEConnectionAttempt(); emit requestICEConnectionAttempt();
} }
} }

View file

@ -31,67 +31,79 @@ class DomainHandler : public QObject {
Q_OBJECT Q_OBJECT
public: public:
DomainHandler(QObject* parent = 0); DomainHandler(QObject* parent = 0);
void clearConnectionInfo(); void clearConnectionInfo();
void clearSettings(); void clearSettings();
const QUuid& getUUID() const { return _uuid; } const QUuid& getUUID() const { return _uuid; }
void setUUID(const QUuid& uuid); void setUUID(const QUuid& uuid);
const QString& getHostname() const { return _hostname; } const QString& getHostname() const { return _hostname; }
const QHostAddress& getIP() const { return _sockAddr.getAddress(); } const QHostAddress& getIP() const { return _sockAddr.getAddress(); }
void setIPToLocalhost() { _sockAddr.setAddress(QHostAddress(QHostAddress::LocalHost)); } void setIPToLocalhost() { _sockAddr.setAddress(QHostAddress(QHostAddress::LocalHost)); }
const HifiSockAddr& getSockAddr() { return _sockAddr; } const HifiSockAddr& getSockAddr() { return _sockAddr; }
void setSockAddr(const HifiSockAddr& sockAddr, const QString& hostname); void setSockAddr(const HifiSockAddr& sockAddr, const QString& hostname);
unsigned short getPort() const { return _sockAddr.getPort(); } unsigned short getPort() const { return _sockAddr.getPort(); }
void setPort(quint16 port) { _sockAddr.setPort(port); } void setPort(quint16 port) { _sockAddr.setPort(port); }
const QUuid& getAssignmentUUID() const { return _assignmentUUID; } const QUuid& getAssignmentUUID() const { return _assignmentUUID; }
void setAssignmentUUID(const QUuid& assignmentUUID) { _assignmentUUID = assignmentUUID; } void setAssignmentUUID(const QUuid& assignmentUUID) { _assignmentUUID = assignmentUUID; }
const QUuid& getICEDomainID() const { return _iceDomainID; } const QUuid& getICEDomainID() const { return _iceDomainID; }
const QUuid& getICEClientID() const { return _iceClientID; } const QUuid& getICEClientID() const { return _iceClientID; }
bool requiresICE() const { return !_iceServerSockAddr.isNull(); } bool requiresICE() const { return !_iceServerSockAddr.isNull(); }
const HifiSockAddr& getICEServerSockAddr() const { return _iceServerSockAddr; } const HifiSockAddr& getICEServerSockAddr() const { return _iceServerSockAddr; }
NetworkPeer& getICEPeer() { return _icePeer; } NetworkPeer& getICEPeer() { return _icePeer; }
void activateICELocalSocket(); void activateICELocalSocket();
void activateICEPublicSocket(); void activateICEPublicSocket();
bool isConnected() const { return _isConnected; } bool isConnected() const { return _isConnected; }
void setIsConnected(bool isConnected); void setIsConnected(bool isConnected);
bool hasSettings() const { return !_settingsObject.isEmpty(); } bool hasSettings() const { return !_settingsObject.isEmpty(); }
void requestDomainSettings(); void requestDomainSettings();
const QJsonObject& getSettingsObject() const { return _settingsObject; } const QJsonObject& getSettingsObject() const { return _settingsObject; }
void parseDTLSRequirementPacket(const QByteArray& dtlsRequirementPacket); void parseDTLSRequirementPacket(const QByteArray& dtlsRequirementPacket);
void processICEResponsePacket(const QByteArray& icePacket); void processICEResponsePacket(const QByteArray& icePacket);
void setPendingPath(const QString& pendingPath) { _pendingPath = pendingPath; }
const QString& getPendingPath() { return _pendingPath; }
void clearPendingPath() { _pendingPath.clear(); }
bool isSocketKnown() const { return !_sockAddr.getAddress().isNull(); }
void softReset(); void softReset();
public slots: public slots:
void setHostnameAndPort(const QString& hostname, quint16 port = DEFAULT_DOMAIN_SERVER_PORT); void setHostnameAndPort(const QString& hostname, quint16 port = DEFAULT_DOMAIN_SERVER_PORT);
void setIceServerHostnameAndID(const QString& iceServerHostname, const QUuid& id); void setIceServerHostnameAndID(const QString& iceServerHostname, const QUuid& id);
private slots: private slots:
void completedHostnameLookup(const QHostInfo& hostInfo); void completedHostnameLookup(const QHostInfo& hostInfo);
void settingsRequestFinished(); void settingsRequestFinished();
signals: signals:
void hostnameChanged(const QString& hostname); void hostnameChanged(const QString& hostname);
// NOTE: the emission of completedSocketDiscovery does not mean a connection to DS is established
// It means that, either from DNS lookup or ICE, we think we have a socket we can talk to DS on
void completedSocketDiscovery();
void connectedToDomain(const QString& hostname); void connectedToDomain(const QString& hostname);
void disconnectedFromDomain(); void disconnectedFromDomain();
void requestICEConnectionAttempt(); void requestICEConnectionAttempt();
void settingsReceived(const QJsonObject& domainSettingsObject); void settingsReceived(const QJsonObject& domainSettingsObject);
void settingsReceiveFail(); void settingsReceiveFail();
private: private:
void hardReset(); void hardReset();
QUuid _uuid; QUuid _uuid;
QString _hostname; QString _hostname;
HifiSockAddr _sockAddr; HifiSockAddr _sockAddr;
@ -103,6 +115,7 @@ private:
bool _isConnected; bool _isConnected;
QJsonObject _settingsObject; QJsonObject _settingsObject;
int _failedSettingsRequests; int _failedSettingsRequests;
QString _pendingPath;
}; };
#endif // hifi_DomainHandler_h #endif // hifi_DomainHandler_h

View file

@ -29,26 +29,27 @@ public:
HifiSockAddr(const HifiSockAddr& otherSockAddr); HifiSockAddr(const HifiSockAddr& otherSockAddr);
HifiSockAddr(const QString& hostname, quint16 hostOrderPort, bool shouldBlockForLookup = false); HifiSockAddr(const QString& hostname, quint16 hostOrderPort, bool shouldBlockForLookup = false);
HifiSockAddr(const sockaddr* sockaddr); HifiSockAddr(const sockaddr* sockaddr);
bool isNull() const { return _address.isNull() && _port == 0; } bool isNull() const { return _address.isNull() && _port == 0; }
void clear() { _address = QHostAddress::Null; _port = 0;}
HifiSockAddr& operator=(const HifiSockAddr& rhsSockAddr); HifiSockAddr& operator=(const HifiSockAddr& rhsSockAddr);
void swap(HifiSockAddr& otherSockAddr); void swap(HifiSockAddr& otherSockAddr);
bool operator==(const HifiSockAddr& rhsSockAddr) const; bool operator==(const HifiSockAddr& rhsSockAddr) const;
bool operator!=(const HifiSockAddr& rhsSockAddr) const { return !(*this == rhsSockAddr); } bool operator!=(const HifiSockAddr& rhsSockAddr) const { return !(*this == rhsSockAddr); }
const QHostAddress& getAddress() const { return _address; } const QHostAddress& getAddress() const { return _address; }
QHostAddress* getAddressPointer() { return &_address; } QHostAddress* getAddressPointer() { return &_address; }
void setAddress(const QHostAddress& address) { _address = address; } void setAddress(const QHostAddress& address) { _address = address; }
quint16 getPort() const { return _port; } quint16 getPort() const { return _port; }
quint16* getPortPointer() { return &_port; } quint16* getPortPointer() { return &_port; }
void setPort(quint16 port) { _port = port; } void setPort(quint16 port) { _port = port; }
static int packSockAddr(unsigned char* packetData, const HifiSockAddr& packSockAddr); static int packSockAddr(unsigned char* packetData, const HifiSockAddr& packSockAddr);
static int unpackSockAddr(const unsigned char* packetData, HifiSockAddr& unpackDestSockAddr); static int unpackSockAddr(const unsigned char* packetData, HifiSockAddr& unpackDestSockAddr);
friend QDebug operator<<(QDebug debug, const HifiSockAddr& sockAddr); friend QDebug operator<<(QDebug debug, const HifiSockAddr& sockAddr);
friend QDataStream& operator<<(QDataStream& dataStream, const HifiSockAddr& sockAddr); friend QDataStream& operator<<(QDataStream& dataStream, const HifiSockAddr& sockAddr);
friend QDataStream& operator>>(QDataStream& dataStream, HifiSockAddr& sockAddr); friend QDataStream& operator>>(QDataStream& dataStream, HifiSockAddr& sockAddr);

View file

@ -54,7 +54,12 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned
connect(addressManager.data(), &AddressManager::possibleDomainChangeRequiredViaICEForID, connect(addressManager.data(), &AddressManager::possibleDomainChangeRequiredViaICEForID,
&_domainHandler, &DomainHandler::setIceServerHostnameAndID); &_domainHandler, &DomainHandler::setIceServerHostnameAndID);
connect(addressManager.data(), &AddressManager::pathChangeRequired, this, &NodeList::sendDSPathQuery); // handle a request for a path change from the AddressManager
connect(addressManager.data(), &AddressManager::pathChangeRequired, this, &NodeList::handleDSPathQuery);
// in case we don't know how to talk to DS when a path change is requested
// fire off any pending DS path query when we get socket information
connect(&_domainHandler, &DomainHandler::completedSocketDiscovery, this, &NodeList::sendPendingDSPathQuery);
// clear our NodeList when the domain changes // clear our NodeList when the domain changes
connect(&_domainHandler, &DomainHandler::disconnectedFromDomain, this, &NodeList::reset); connect(&_domainHandler, &DomainHandler::disconnectedFromDomain, this, &NodeList::reset);
@ -401,9 +406,34 @@ void NodeList::sendDomainServerCheckIn() {
} }
} }
void NodeList::handleDSPathQuery(const QString& newPath) {
if (_domainHandler.isSocketKnown()) {
// if we have a DS socket we assume it will get this packet and send if off right away
sendDSPathQuery(newPath);
} else {
// otherwise we make it pending so that it can be sent once a connection is established
_domainHandler.setPendingPath(newPath);
}
}
void NodeList::sendPendingDSPathQuery() {
QString pendingPath = _domainHandler.getPendingPath();
if (!pendingPath.isEmpty()) {
qCDebug(networking) << "Attemping to send pending query to DS for path" << pendingPath;
// this is a slot triggered if we just established a network link with a DS and want to send a path query
sendDSPathQuery(_domainHandler.getPendingPath());
// clear whatever the pending path was
_domainHandler.clearPendingPath();
}
}
void NodeList::sendDSPathQuery(const QString& newPath) { void NodeList::sendDSPathQuery(const QString& newPath) {
// only send a path query if we know who our DS is or is going to be // only send a path query if we know who our DS is or is going to be
if (!_domainHandler.getSockAddr().isNull()) { if (_domainHandler.isSocketKnown()) {
// construct the path query packet // construct the path query packet
QByteArray pathQueryPacket = byteArrayWithPopulatedHeader(PacketTypeDomainServerPathQuery); QByteArray pathQueryPacket = byteArrayWithPopulatedHeader(PacketTypeDomainServerPathQuery);
@ -420,12 +450,13 @@ void NodeList::sendDSPathQuery(const QString& newPath) {
// append the path itself to the query packet // append the path itself to the query packet
pathQueryPacket.append(pathQueryUTF8); pathQueryPacket.append(pathQueryUTF8);
qDebug() << "Sending a path query packet for path" << newPath << "to domain-server at" << _domainHandler.getSockAddr(); qCDebug(networking) << "Sending a path query packet for path" << newPath << "to domain-server at"
<< _domainHandler.getSockAddr();
// send off the path query // send off the path query
writeUnverifiedDatagram(pathQueryPacket, _domainHandler.getSockAddr()); writeUnverifiedDatagram(pathQueryPacket, _domainHandler.getSockAddr());
} else { } else {
qDebug() << "Path" << newPath << "would make PacketTypeDomainServerPathQuery packet > MAX_PACKET_SIZE." << qCDebug(networking) << "Path" << newPath << "would make PacketTypeDomainServerPathQuery packet > MAX_PACKET_SIZE." <<
"Will not send query."; "Will not send query.";
} }
} }
@ -462,9 +493,10 @@ void NodeList::handleDSPathQueryResponse(const QByteArray& packet) {
// Hand it off to the AddressManager so it can handle it as a relative viewpoint // Hand it off to the AddressManager so it can handle it as a relative viewpoint
if (DependencyManager::get<AddressManager>()->goToViewpoint(viewpoint)) { if (DependencyManager::get<AddressManager>()->goToViewpoint(viewpoint)) {
qDebug() << "Going to viewpoint" << viewpoint << "which was the lookup result for path" << pathQuery; qCDebug(networking) << "Going to viewpoint" << viewpoint << "which was the lookup result for path" << pathQuery;
} else { } else {
qDebug() << "Could not go to viewpoint" << viewpoint << "which was the lookup result for path" << pathQuery; qCDebug(networking) << "Could not go to viewpoint" << viewpoint
<< "which was the lookup result for path" << pathQuery;
} }
} }
} }

View file

@ -71,9 +71,11 @@ public slots:
void reset(); void reset();
void sendDomainServerCheckIn(); void sendDomainServerCheckIn();
void pingInactiveNodes(); void pingInactiveNodes();
void sendDSPathQuery(const QString& newPath); void handleDSPathQuery(const QString& newPath);
signals: signals:
void limitOfSilentDomainCheckInsReached(); void limitOfSilentDomainCheckInsReached();
private slots:
void sendPendingDSPathQuery();
private: private:
NodeList() : LimitedNodeList(0, 0) { assert(false); } // Not implemented, needed for DependencyManager templates compile NodeList() : LimitedNodeList(0, 0) { assert(false); } // Not implemented, needed for DependencyManager templates compile
NodeList(char ownerType, unsigned short socketListenPort = 0, unsigned short dtlsListenPort = 0); NodeList(char ownerType, unsigned short socketListenPort = 0, unsigned short dtlsListenPort = 0);
@ -92,6 +94,8 @@ private:
void handleDSPathQueryResponse(const QByteArray& packet); void handleDSPathQueryResponse(const QByteArray& packet);
void sendDSPathQuery(const QString& newPath);
NodeType_t _ownerType; NodeType_t _ownerType;
NodeSet _nodeTypesOfInterest; NodeSet _nodeTypesOfInterest;
DomainHandler _domainHandler; DomainHandler _domainHandler;