build out more of the ice-server, make connect requests from NodeList

This commit is contained in:
Stephen Birarda 2014-10-02 13:39:58 -07:00
parent 9baf983d07
commit cca1c30207
10 changed files with 154 additions and 55 deletions

View file

@ -9,10 +9,62 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <PacketHeaders.h>
#include "IceServer.h"
IceServer::IceServer(int argc, char* argv[]) :
QCoreApplication(argc, argv)
QCoreApplication(argc, argv),
_serverSocket()
{
// start the ice-server socket
qDebug() << "ice-server socket is listening on" << ICE_SERVER_DEFAULT_PORT;
_serverSocket.bind(QHostAddress::AnyIPv4, ICE_SERVER_DEFAULT_PORT);
// call our process datagrams slot when the UDP socket has packets ready
connect(&_serverSocket, &QUdpSocket::readyRead, this, &IceServer::processDatagrams);
}
void IceServer::processDatagrams() {
HifiSockAddr sendingSockAddr;
QByteArray incomingPacket;
while (_serverSocket.hasPendingDatagrams()) {
incomingPacket.resize(_serverSocket.pendingDatagramSize());
_serverSocket.readDatagram(incomingPacket.data(), incomingPacket.size(),
sendingSockAddr.getAddressPointer(), sendingSockAddr.getPortPointer());
if (packetTypeForPacket(incomingPacket) == PacketTypeIceServerHeartbeat) {
QUuid senderUUID = uuidFromPacketHeader(incomingPacket);
// pull the public and private sock addrs for this peer
HifiSockAddr publicSocket, localSocket;
QDataStream hearbeatStream(incomingPacket);
hearbeatStream.skipRawData(numBytesForPacketHeader(incomingPacket));
hearbeatStream >> publicSocket >> localSocket;
// make sure we have this sender in our peer hash
SharedNetworkPeer matchingPeer = _activePeers.value(senderUUID);
if (!matchingPeer) {
// if we don't have this sender we need to create them now
matchingPeer = SharedNetworkPeer(new NetworkPeer(senderUUID, publicSocket, localSocket));
qDebug() << "Added a new network peer" << *matchingPeer;
} else {
// we already had the peer so just potentially update their sockets
matchingPeer->setPublicSocket(publicSocket);
matchingPeer->setLocalSocket(localSocket);
}
// check if this node also included a UUID that they would like to connect to
QUuid connectRequestUUID;
hearbeatStream >> connectRequestUUID;
}
}
}

View file

@ -12,11 +12,20 @@
#ifndef hifi_IceServer_h
#define hifi_IceServer_h
#include <QCoreApplication>
#include <qcoreapplication.h>
#include <qsharedpointer.h>
#include <qudpsocket.h>
#include <NetworkPeer.h>
class IceServer : public QCoreApplication {
public:
IceServer(int argc, char* argv[]);
private slots:
void processDatagrams();
private:
QHash<QUuid, SharedNetworkPeer> _activePeers;
QUdpSocket _serverSocket;
};
#endif // hifi_IceServer_h

View file

@ -25,6 +25,7 @@ DomainHandler::DomainHandler(QObject* parent) :
_uuid(),
_sockAddr(HifiSockAddr(QHostAddress::Null, DEFAULT_DOMAIN_SERVER_PORT)),
_assignmentUUID(),
_requiresICE(true),
_isConnected(false),
_handshakeTimer(NULL),
_settingsObject(),
@ -35,6 +36,7 @@ DomainHandler::DomainHandler(QObject* parent) :
void DomainHandler::clearConnectionInfo() {
_uuid = QUuid();
_requiresICE = true;
_isConnected = false;
emit disconnectedFromDomain();

View file

@ -54,6 +54,8 @@ public:
const QUuid& getAssignmentUUID() const { return _assignmentUUID; }
void setAssignmentUUID(const QUuid& assignmentUUID) { _assignmentUUID = assignmentUUID; }
bool requiresICE() const { return _requiresICE; }
bool isConnected() const { return _isConnected; }
void setIsConnected(bool isConnected);
@ -85,6 +87,7 @@ private:
QString _hostname;
HifiSockAddr _sockAddr;
QUuid _assignmentUUID;
bool _requiresICE;
bool _isConnected;
QTimer* _handshakeTimer;
QJsonObject _settingsObject;

View file

@ -63,4 +63,11 @@ void NetworkPeer::activatePublicSocket() {
void NetworkPeer::activateSymmetricSocket() {
qDebug() << "Activating symmetric socket for network peer with ID" << uuidStringWithoutCurlyBraces(_uuid);
_activeSocket = &_symmetricSocket;
}
QDebug operator<<(QDebug debug, const NetworkPeer &peer) {
debug << uuidStringWithoutCurlyBraces(peer.getUUID())
<< "- public:" << peer.getPublicSocket()
<< "- local:" << peer.getLocalSocket();
return debug;
}

View file

@ -17,10 +17,16 @@
#include "HifiSockAddr.h"
const QString ICE_SERVER_HOSTNAME = "localhost";
const int ICE_SERVER_DEFAULT_PORT = 7337;
class NetworkPeer : public QObject {
public:
NetworkPeer(const QUuid& uuid, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket);
const QUuid& getUUID() const { return _uuid; }
void setUUID(const QUuid& uuid) { _uuid = uuid; }
const HifiSockAddr& getPublicSocket() const { return _publicSocket; }
void setPublicSocket(const HifiSockAddr& publicSocket);
const HifiSockAddr& getLocalSocket() const { return _localSocket; }
@ -43,4 +49,7 @@ protected:
HifiSockAddr* _activeSocket;
};
QDebug operator<<(QDebug debug, const NetworkPeer &peer);
typedef QSharedPointer<NetworkPeer> SharedNetworkPeer;
#endif // hifi_NetworkPeer_h

View file

@ -57,9 +57,6 @@ public:
char getType() const { return _type; }
void setType(char type) { _type = type; }
const QUuid& getUUID() const { return _uuid; }
void setUUID(const QUuid& uuid) { _uuid = uuid; }
quint64 getWakeTimestamp() const { return _wakeTimestamp; }
void setWakeTimestamp(quint64 wakeTimestamp) { _wakeTimestamp = wakeTimestamp; }

View file

@ -243,61 +243,78 @@ void NodeList::sendDomainServerCheckIn() {
// send a STUN request to figure it out
sendSTUNRequest();
} else if (!_domainHandler.getIP().isNull()) {
bool isUsingDTLS = false;
PacketType domainPacketType = !_domainHandler.isConnected()
if (!_domainHandler.isConnected() && _domainHandler.requiresICE()) {
sendICERequestForDomainConnection();
} else {
bool isUsingDTLS = false;
PacketType domainPacketType = !_domainHandler.isConnected()
? PacketTypeDomainConnectRequest : PacketTypeDomainListRequest;
if (!_domainHandler.isConnected()) {
qDebug() << "Sending connect request to domain-server at" << _domainHandler.getHostname();
if (!_domainHandler.isConnected()) {
qDebug() << "Sending connect request to domain-server at" << _domainHandler.getHostname();
}
// construct the DS check in packet
QUuid packetUUID = _sessionUUID;
if (!_domainHandler.getAssignmentUUID().isNull() && domainPacketType == PacketTypeDomainConnectRequest) {
// this is a connect request and we're an assigned node
// so set our packetUUID as the assignment UUID
packetUUID = _domainHandler.getAssignmentUUID();
}
QByteArray domainServerPacket = byteArrayWithPopulatedHeader(domainPacketType, packetUUID);
QDataStream packetStream(&domainServerPacket, QIODevice::Append);
// pack our data to send to the domain-server
packetStream << _ownerType << _publicSockAddr
<< HifiSockAddr(QHostAddress(getHostOrderLocalAddress()), _nodeSocket.localPort())
<< (quint8) _nodeTypesOfInterest.size();
// copy over the bytes for node types of interest, if required
foreach (NodeType_t nodeTypeOfInterest, _nodeTypesOfInterest) {
packetStream << nodeTypeOfInterest;
}
if (!isUsingDTLS) {
writeDatagram(domainServerPacket, _domainHandler.getSockAddr(), QUuid());
}
const int NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST = 5;
static unsigned int numDomainCheckins = 0;
// send a STUN request every Nth domain server check in so we update our public socket, if required
if (numDomainCheckins++ % NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST == 0) {
sendSTUNRequest();
}
if (_numNoReplyDomainCheckIns >= MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
// we haven't heard back from DS in MAX_SILENT_DOMAIN_SERVER_CHECK_INS
// so emit our signal that indicates that
emit limitOfSilentDomainCheckInsReached();
}
// increment the count of un-replied check-ins
_numNoReplyDomainCheckIns++;
}
// construct the DS check in packet
QUuid packetUUID = _sessionUUID;
if (!_domainHandler.getAssignmentUUID().isNull() && domainPacketType == PacketTypeDomainConnectRequest) {
// this is a connect request and we're an assigned node
// so set our packetUUID as the assignment UUID
packetUUID = _domainHandler.getAssignmentUUID();
}
QByteArray domainServerPacket = byteArrayWithPopulatedHeader(domainPacketType, packetUUID);
QDataStream packetStream(&domainServerPacket, QIODevice::Append);
// pack our data to send to the domain-server
packetStream << _ownerType << _publicSockAddr
<< HifiSockAddr(QHostAddress(getHostOrderLocalAddress()), _nodeSocket.localPort())
<< (quint8) _nodeTypesOfInterest.size();
// copy over the bytes for node types of interest, if required
foreach (NodeType_t nodeTypeOfInterest, _nodeTypesOfInterest) {
packetStream << nodeTypeOfInterest;
}
if (!isUsingDTLS) {
writeDatagram(domainServerPacket, _domainHandler.getSockAddr(), QUuid());
}
const int NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST = 5;
static unsigned int numDomainCheckins = 0;
// send a STUN request every Nth domain server check in so we update our public socket, if required
if (numDomainCheckins++ % NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST == 0) {
sendSTUNRequest();
}
if (_numNoReplyDomainCheckIns >= MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
// we haven't heard back from DS in MAX_SILENT_DOMAIN_SERVER_CHECK_INS
// so emit our signal that indicates that
emit limitOfSilentDomainCheckInsReached();
}
// increment the count of un-replied check-ins
_numNoReplyDomainCheckIns++;
}
}
void NodeList::sendICERequestForDomainConnection() {
QByteArray iceRequestByteArray = byteArrayWithPopulatedHeader(PacketTypeIceServerHeartbeat);
QDataStream iceDataStream(&iceRequestByteArray, QIODevice::Append);
iceDataStream << _publicSockAddr << HifiSockAddr(QHostAddress(getHostOrderLocalAddress()), _nodeSocket.localPort());
iceDataStream << _domainHandler.getUUID();
qDebug() << "Sending packet to ICE server to request connection info for peer with ID"
<< uuidStringWithoutCurlyBraces(_domainHandler.getUUID());
_nodeSocket.writeDatagram(iceRequestByteArray, QHostAddress::LocalHost, ICE_SERVER_DEFAULT_PORT);
}
int NodeList::processDomainServerList(const QByteArray& packet) {
// this is a packet from the domain server, reset the count of un-replied check-ins
_numNoReplyDomainCheckIns = 0;

View file

@ -91,6 +91,8 @@ private:
void sendSTUNRequest();
bool processSTUNResponse(const QByteArray& packet);
void sendICERequestForDomainConnection();
void processDomainServerAuthRequest(const QByteArray& packet);
void requestAuthForDomainServer();
void activateSocketFromNodeCommunication(const QByteArray& packet, const SharedNodePointer& sendingNode);

View file

@ -70,7 +70,8 @@ enum PacketType {
PacketTypeVoxelEditNack,
PacketTypeParticleEditNack,
PacketTypeEntityEditNack, // 48
PacketTypeSignedTransactionPayment
PacketTypeSignedTransactionPayment,
PacketTypeIceServerHeartbeat
};
typedef char PacketVersion;