mirror of
https://github.com/overte-org/overte.git
synced 2025-06-16 15:40:12 +02:00
initial handshaking for DTLS sessions between DS and clients
This commit is contained in:
parent
dc3a4d4957
commit
e1cae6d295
19 changed files with 200 additions and 72 deletions
|
@ -797,7 +797,7 @@ AnimationServer::AnimationServer(int &argc, char **argv) :
|
||||||
|
|
||||||
QTimer* domainServerTimer = new QTimer(this);
|
QTimer* domainServerTimer = new QTimer(this);
|
||||||
connect(domainServerTimer, SIGNAL(timeout()), nodeList, SLOT(sendDomainServerCheckIn()));
|
connect(domainServerTimer, SIGNAL(timeout()), nodeList, SLOT(sendDomainServerCheckIn()));
|
||||||
domainServerTimer->start(DOMAIN_SERVER_CHECK_IN_USECS / 1000);
|
domainServerTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS);
|
||||||
|
|
||||||
QTimer* silentNodeTimer = new QTimer(this);
|
QTimer* silentNodeTimer = new QTimer(this);
|
||||||
connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes()));
|
connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes()));
|
||||||
|
|
|
@ -369,7 +369,7 @@ void AudioMixer::sendStatsPacket() {
|
||||||
statsObject["average_mixes_per_listener"] = 0.0;
|
statsObject["average_mixes_per_listener"] = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadedAssignment::addPacketStatsAndSendStatsPacket(statsObject);
|
// ThreadedAssignment::addPacketStatsAndSendStatsPacket(statsObject);
|
||||||
|
|
||||||
_sumListeners = 0;
|
_sumListeners = 0;
|
||||||
_sumMixes = 0;
|
_sumMixes = 0;
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#ifndef __hifi__DTLSServerSession__
|
#ifndef __hifi__DTLSServerSession__
|
||||||
#define __hifi__DTLSServerSession__
|
#define __hifi__DTLSServerSession__
|
||||||
|
|
||||||
|
#include <gnutls/dtls.h>
|
||||||
|
|
||||||
#include <DTLSSession.h>
|
#include <DTLSSession.h>
|
||||||
|
|
||||||
class DTLSServerSession : public DTLSSession {
|
class DTLSServerSession : public DTLSSession {
|
||||||
|
|
|
@ -96,8 +96,12 @@ bool DomainServer::optionallySetupDTLS() {
|
||||||
// set the D-H paramters on the X509 credentials
|
// set the D-H paramters on the X509 credentials
|
||||||
gnutls_certificate_set_dh_params(*_x509Credentials, *_dhParams);
|
gnutls_certificate_set_dh_params(*_x509Credentials, *_dhParams);
|
||||||
|
|
||||||
|
// setup the key used for cookie verification
|
||||||
|
_cookieKey = new gnutls_datum_t;
|
||||||
|
gnutls_key_generate(_cookieKey, GNUTLS_COOKIE_KEY_SIZE);
|
||||||
|
|
||||||
_priorityCache = new gnutls_priority_t;
|
_priorityCache = new gnutls_priority_t;
|
||||||
const char DTLS_PRIORITY_STRING[] = "PERFORMANCE:-VERS-TLS-ALL:+VERS-DTLS1.2:%SERVER_PRECEDENCE";
|
const char DTLS_PRIORITY_STRING[] = "PERFORMANCE:-VERS-TLS-ALL:+VERS-DTLS1.0:%SERVER_PRECEDENCE";
|
||||||
gnutls_priority_init(_priorityCache, DTLS_PRIORITY_STRING, NULL);
|
gnutls_priority_init(_priorityCache, DTLS_PRIORITY_STRING, NULL);
|
||||||
|
|
||||||
_isUsingDTLS = true;
|
_isUsingDTLS = true;
|
||||||
|
@ -612,20 +616,55 @@ void DomainServer::readAvailableDTLSDatagrams() {
|
||||||
static socklen_t sockAddrSize = sizeof(senderSockAddr);
|
static socklen_t sockAddrSize = sizeof(senderSockAddr);
|
||||||
|
|
||||||
while (dtlsSocket.hasPendingDatagrams()) {
|
while (dtlsSocket.hasPendingDatagrams()) {
|
||||||
|
qDebug() << "Looking at a datagram";
|
||||||
|
|
||||||
// check if we have an active DTLS session for this sender
|
// check if we have an active DTLS session for this sender
|
||||||
QByteArray peekDatagram(dtlsSocket.pendingDatagramSize(), 0);
|
QByteArray peekDatagram(dtlsSocket.pendingDatagramSize(), 0);
|
||||||
|
|
||||||
recvfrom(dtlsSocket.socketDescriptor(), peekDatagram.data(), dtlsSocket.pendingDatagramSize(),
|
recvfrom(dtlsSocket.socketDescriptor(), peekDatagram.data(), dtlsSocket.pendingDatagramSize(),
|
||||||
MSG_PEEK, &senderSockAddr, &sockAddrSize);
|
MSG_PEEK, &senderSockAddr, &sockAddrSize);
|
||||||
|
|
||||||
DTLSSession* existingSession = _dtlsSessions.value(HifiSockAddr(&senderSockAddr));
|
HifiSockAddr senderHifiSockAddr(&senderSockAddr);
|
||||||
|
DTLSServerSession* existingSession = _dtlsSessions.value(senderHifiSockAddr);
|
||||||
qDebug() << "Checking for a session with" << HifiSockAddr(&senderSockAddr);
|
|
||||||
|
|
||||||
if (existingSession) {
|
if (existingSession) {
|
||||||
// use GnuTLS to receive the encrypted data
|
// check if we have completed handshake with this user
|
||||||
|
int handshakeReturn = gnutls_handshake(*existingSession->getGnuTLSSession());
|
||||||
|
qDebug() << "Handshake return for user is" << handshakeReturn;
|
||||||
} else {
|
} else {
|
||||||
// no existing session - set up a new session now
|
// first we verify the cookie
|
||||||
|
// see http://gnutls.org/manual/html_node/DTLS-sessions.html for why this is required
|
||||||
|
gnutls_dtls_prestate_st prestate;
|
||||||
|
memset(&prestate, 0, sizeof(prestate));
|
||||||
|
int cookieValid = gnutls_dtls_cookie_verify(_cookieKey, &senderSockAddr, sizeof(senderSockAddr),
|
||||||
|
peekDatagram.data(), peekDatagram.size(), &prestate);
|
||||||
|
|
||||||
|
if (cookieValid < 0) {
|
||||||
|
// the cookie sent by the client was not valid
|
||||||
|
// send a valid one
|
||||||
|
DTLSServerSession tempServerSession(LimitedNodeList::getInstance()->getDTLSSocket(), senderHifiSockAddr);
|
||||||
|
gnutls_dtls_cookie_send(_cookieKey, &senderSockAddr, sizeof(senderSockAddr), &prestate,
|
||||||
|
&tempServerSession, DTLSSession::socketPush);
|
||||||
|
|
||||||
|
// acutally pull the peeked data off the network stack so that it gets discarded
|
||||||
|
dtlsSocket.readDatagram(peekDatagram.data(), peekDatagram.size());
|
||||||
|
} else {
|
||||||
|
// cookie valid but no existing session - set up a new session now
|
||||||
|
DTLSServerSession* newServerSession = new DTLSServerSession(LimitedNodeList::getInstance()->getDTLSSocket(),
|
||||||
|
senderHifiSockAddr);
|
||||||
|
gnutls_session_t* gnutlsSession = newServerSession->getGnuTLSSession();
|
||||||
|
|
||||||
|
gnutls_priority_set(*gnutlsSession, *_priorityCache);
|
||||||
|
gnutls_credentials_set(*gnutlsSession, GNUTLS_CRD_CERTIFICATE, *_x509Credentials);
|
||||||
|
gnutls_dtls_prestate_set(*gnutlsSession, &prestate);
|
||||||
|
|
||||||
|
// handshake to begin the session
|
||||||
|
int handshakeReturn = gnutls_handshake(*gnutlsSession);
|
||||||
|
qDebug() << "initial handshake return" << handshakeReturn;
|
||||||
|
|
||||||
|
qDebug() << "Beginning DTLS session with node at" << senderHifiSockAddr;
|
||||||
|
_dtlsSessions[senderHifiSockAddr] = newServerSession;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,7 @@ private:
|
||||||
bool _isUsingDTLS;
|
bool _isUsingDTLS;
|
||||||
gnutls_certificate_credentials_t* _x509Credentials;
|
gnutls_certificate_credentials_t* _x509Credentials;
|
||||||
gnutls_dh_params_t* _dhParams;
|
gnutls_dh_params_t* _dhParams;
|
||||||
|
gnutls_datum_t* _cookieKey;
|
||||||
gnutls_priority_t* _priorityCache;
|
gnutls_priority_t* _priorityCache;
|
||||||
|
|
||||||
QHash<HifiSockAddr, DTLSServerSession*> _dtlsSessions;
|
QHash<HifiSockAddr, DTLSServerSession*> _dtlsSessions;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <QtNetwork/QNetworkReply>
|
#include <QtNetwork/QNetworkReply>
|
||||||
#include <qendian.h>
|
#include <qendian.h>
|
||||||
|
|
||||||
|
#include <LimitedNodeList.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
#include "AudioRingBuffer.h"
|
#include "AudioRingBuffer.h"
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
|
|
||||||
#include <SharedUtil.h>
|
#include <LimitedNodeList.h>
|
||||||
|
|
||||||
#include "DatagramSequencer.h"
|
#include "DatagramSequencer.h"
|
||||||
#include "MetavoxelMessages.h"
|
#include "MetavoxelMessages.h"
|
||||||
|
|
|
@ -8,8 +8,28 @@
|
||||||
|
|
||||||
#include "DTLSClientSession.h"
|
#include "DTLSClientSession.h"
|
||||||
|
|
||||||
|
gnutls_certificate_credentials_t* DTLSClientSession::x509CACredentials() {
|
||||||
|
static gnutls_certificate_credentials_t x509Credentials;
|
||||||
|
static bool credentialsInitialized = false;
|
||||||
|
|
||||||
|
if (!credentialsInitialized) {
|
||||||
|
gnutls_certificate_allocate_credentials(&x509Credentials);
|
||||||
|
qDebug() << "processed" << gnutls_certificate_set_x509_trust_file(x509Credentials, "/Users/birarda/code/hifi/certs/root-ca.crt", GNUTLS_X509_FMT_PEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
return &x509Credentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
int verifyX509Certificate(gnutls_session_t session) {
|
||||||
|
int certificateType = gnutls_certificate_type_get(session);
|
||||||
|
qDebug() << "Verifying a certificate of type" << certificateType;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
DTLSClientSession::DTLSClientSession(QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket) :
|
DTLSClientSession::DTLSClientSession(QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket) :
|
||||||
DTLSSession(GNUTLS_CLIENT, dtlsSocket, destinationSocket)
|
DTLSSession(GNUTLS_CLIENT, dtlsSocket, destinationSocket)
|
||||||
{
|
{
|
||||||
gnutls_credentials_set(_gnutlsSession, GNUTLS_CRD_CERTIFICATE, DTLSSession::x509CACredentials());
|
gnutls_priority_set_direct(_gnutlsSession, "PERFORMANCE", NULL);
|
||||||
|
gnutls_credentials_set(_gnutlsSession, GNUTLS_CRD_CERTIFICATE, x509CACredentials());
|
||||||
}
|
}
|
|
@ -14,6 +14,8 @@
|
||||||
class DTLSClientSession : public DTLSSession {
|
class DTLSClientSession : public DTLSSession {
|
||||||
public:
|
public:
|
||||||
DTLSClientSession(QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket);
|
DTLSClientSession(QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket);
|
||||||
|
|
||||||
|
static gnutls_certificate_credentials_t* x509CACredentials();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__hifi__DTLSClientSession__) */
|
#endif /* defined(__hifi__DTLSClientSession__) */
|
||||||
|
|
|
@ -8,46 +8,88 @@
|
||||||
|
|
||||||
#include <gnutls/dtls.h>
|
#include <gnutls/dtls.h>
|
||||||
|
|
||||||
|
#include "NodeList.h"
|
||||||
#include "DTLSSession.h"
|
#include "DTLSSession.h"
|
||||||
|
|
||||||
int DTLSSession::socketPullTimeout(gnutls_transport_ptr_t ptr, unsigned int ms) {
|
int DTLSSession::socketPullTimeout(gnutls_transport_ptr_t ptr, unsigned int ms) {
|
||||||
return 1;
|
DTLSSession* session = static_cast<DTLSSession*>(ptr);
|
||||||
|
QUdpSocket& dtlsSocket = session->_dtlsSocket;
|
||||||
|
|
||||||
|
if (dtlsSocket.hasPendingDatagrams()) {
|
||||||
|
// peek the data on stack to see if it belongs to this session
|
||||||
|
static sockaddr senderSockAddr;
|
||||||
|
static socklen_t sockAddrSize = sizeof(senderSockAddr);
|
||||||
|
|
||||||
|
QByteArray peekDatagram(dtlsSocket.pendingDatagramSize(), 0);
|
||||||
|
|
||||||
|
recvfrom(dtlsSocket.socketDescriptor(), peekDatagram.data(), dtlsSocket.pendingDatagramSize(),
|
||||||
|
MSG_PEEK, &senderSockAddr, &sockAddrSize);
|
||||||
|
|
||||||
|
if (HifiSockAddr(&senderSockAddr) == session->_destinationSocket) {
|
||||||
|
// there is data for this session ready to be read
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
// the next data from the dtlsSocket is not for this session
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// no data available on the dtlsSocket
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t DTLSSession::socketPull(gnutls_transport_ptr_t ptr, void* buffer, size_t size) {
|
ssize_t DTLSSession::socketPull(gnutls_transport_ptr_t ptr, void* buffer, size_t size) {
|
||||||
DTLSSession* session = static_cast<DTLSSession*>(ptr);
|
DTLSSession* session = static_cast<DTLSSession*>(ptr);
|
||||||
QUdpSocket& dtlsSocket = session->_dtlsSocket;
|
QUdpSocket& dtlsSocket = session->_dtlsSocket;
|
||||||
|
|
||||||
if (dtlsSocket.hasPendingDatagrams()) {
|
HifiSockAddr pulledSockAddr;
|
||||||
return dtlsSocket.read(reinterpret_cast<char*>(buffer), size);
|
qint64 bytesReceived = dtlsSocket.readDatagram(reinterpret_cast<char*>(buffer), size,
|
||||||
} else {
|
pulledSockAddr.getAddressPointer(), pulledSockAddr.getPortPointer());
|
||||||
gnutls_transport_set_errno(session->_gnutlsSession, GNUTLS_E_AGAIN);
|
if (bytesReceived == -1) {
|
||||||
return 0;
|
// no data to pull, return -1
|
||||||
|
qDebug() << "Received no data on call to readDatagram";
|
||||||
|
return bytesReceived;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pulledSockAddr == session->_destinationSocket) {
|
||||||
|
// bytes received from the correct sender, return number of bytes received
|
||||||
|
qDebug() << "Received" << bytesReceived << "on DTLS socket from" << pulledSockAddr;
|
||||||
|
return bytesReceived;
|
||||||
|
} else {
|
||||||
|
qDebug() << pulledSockAddr << "is not" << session->_destinationSocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we pulled a packet not matching this session, so output that
|
||||||
|
qDebug() << "Denied connection from" << pulledSockAddr;
|
||||||
|
|
||||||
|
gnutls_transport_set_errno(session->_gnutlsSession, GNUTLS_E_AGAIN);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t DTLSSession::socketPush(gnutls_transport_ptr_t ptr, const void* buffer, size_t size) {
|
ssize_t DTLSSession::socketPush(gnutls_transport_ptr_t ptr, const void* buffer, size_t size) {
|
||||||
DTLSSession* session = static_cast<DTLSSession*>(ptr);
|
DTLSSession* session = static_cast<DTLSSession*>(ptr);
|
||||||
QUdpSocket& dtlsSocket = session->_dtlsSocket;
|
QUdpSocket& dtlsSocket = session->_dtlsSocket;
|
||||||
|
|
||||||
|
qDebug() << "Pushing a message of size" << size << "to" << session->_destinationSocket;
|
||||||
return dtlsSocket.writeDatagram(reinterpret_cast<const char*>(buffer), size,
|
return dtlsSocket.writeDatagram(reinterpret_cast<const char*>(buffer), size,
|
||||||
session->_destinationSocket.getAddress(), session->_destinationSocket.getPort());
|
session->_destinationSocket.getAddress(), session->_destinationSocket.getPort());
|
||||||
}
|
}
|
||||||
|
|
||||||
gnutls_certificate_credentials_t* DTLSSession::x509CACredentials() {
|
|
||||||
static gnutls_certificate_credentials_t x509Credentials;
|
|
||||||
static bool credentialsInitialized = false;
|
|
||||||
|
|
||||||
if (!credentialsInitialized) {
|
|
||||||
gnutls_certificate_allocate_credentials(&x509Credentials);
|
|
||||||
}
|
|
||||||
|
|
||||||
return &x509Credentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
DTLSSession::DTLSSession(int end, QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket) :
|
DTLSSession::DTLSSession(int end, QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket) :
|
||||||
_dtlsSocket(dtlsSocket),
|
_dtlsSocket(dtlsSocket),
|
||||||
_destinationSocket(destinationSocket)
|
_destinationSocket(destinationSocket)
|
||||||
{
|
{
|
||||||
gnutls_init(&_gnutlsSession, end | GNUTLS_DATAGRAM);
|
gnutls_init(&_gnutlsSession, end | GNUTLS_DATAGRAM | GNUTLS_NONBLOCK);
|
||||||
|
|
||||||
|
// see http://gnutls.org/manual/html_node/Datagram-TLS-API.html#gnutls_005fdtls_005fset_005fmtu
|
||||||
|
const unsigned int DTLS_MAX_MTU = 1452;
|
||||||
|
gnutls_dtls_set_mtu(_gnutlsSession, DTLS_MAX_MTU);
|
||||||
|
|
||||||
|
const unsigned int DTLS_TOTAL_CONNECTION_TIMEOUT = 10 * DOMAIN_SERVER_CHECK_IN_MSECS;
|
||||||
|
gnutls_dtls_set_timeouts(_gnutlsSession, 0, DTLS_TOTAL_CONNECTION_TIMEOUT);
|
||||||
|
|
||||||
|
gnutls_transport_set_ptr(_gnutlsSession, this);
|
||||||
|
gnutls_transport_set_push_function(_gnutlsSession, socketPush);
|
||||||
|
gnutls_transport_set_pull_function(_gnutlsSession, socketPull);
|
||||||
|
gnutls_transport_set_pull_timeout_function(_gnutlsSession, socketPullTimeout);
|
||||||
}
|
}
|
|
@ -20,12 +20,13 @@ class DTLSSession : public QObject {
|
||||||
public:
|
public:
|
||||||
DTLSSession(int end, QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket);
|
DTLSSession(int end, QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket);
|
||||||
|
|
||||||
static gnutls_certificate_credentials_t* x509CACredentials();
|
|
||||||
protected:
|
|
||||||
static int socketPullTimeout(gnutls_transport_ptr_t ptr, unsigned int ms);
|
static int socketPullTimeout(gnutls_transport_ptr_t ptr, unsigned int ms);
|
||||||
static ssize_t socketPull(gnutls_transport_ptr_t ptr, void* buffer, size_t size);
|
static ssize_t socketPull(gnutls_transport_ptr_t ptr, void* buffer, size_t size);
|
||||||
static ssize_t socketPush(gnutls_transport_ptr_t ptr, const void* buffer, size_t size);
|
static ssize_t socketPush(gnutls_transport_ptr_t ptr, const void* buffer, size_t size);
|
||||||
|
|
||||||
|
gnutls_session_t* getGnuTLSSession() { return &_gnutlsSession; }
|
||||||
|
|
||||||
|
protected:
|
||||||
QUdpSocket& _dtlsSocket;
|
QUdpSocket& _dtlsSocket;
|
||||||
gnutls_session_t _gnutlsSession;
|
gnutls_session_t _gnutlsSession;
|
||||||
HifiSockAddr _destinationSocket;
|
HifiSockAddr _destinationSocket;
|
||||||
|
|
|
@ -18,7 +18,6 @@ DomainHandler::DomainHandler() :
|
||||||
_sockAddr(HifiSockAddr(QHostAddress::Null, DEFAULT_DOMAIN_SERVER_PORT)),
|
_sockAddr(HifiSockAddr(QHostAddress::Null, DEFAULT_DOMAIN_SERVER_PORT)),
|
||||||
_assignmentUUID(),
|
_assignmentUUID(),
|
||||||
_isConnected(false),
|
_isConnected(false),
|
||||||
_requiresDTLS(false),
|
|
||||||
_dtlsSession(NULL)
|
_dtlsSession(NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -31,13 +30,18 @@ DomainHandler::~DomainHandler() {
|
||||||
void DomainHandler::clearConnectionInfo() {
|
void DomainHandler::clearConnectionInfo() {
|
||||||
_uuid = QUuid();
|
_uuid = QUuid();
|
||||||
_isConnected = false;
|
_isConnected = false;
|
||||||
|
|
||||||
|
delete _dtlsSession;
|
||||||
|
_dtlsSession = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DomainHandler::reset() {
|
void DomainHandler::reset() {
|
||||||
clearConnectionInfo();
|
clearConnectionInfo();
|
||||||
_hostname = QString();
|
_hostname = QString();
|
||||||
_sockAddr.setAddress(QHostAddress::Null);
|
_sockAddr.setAddress(QHostAddress::Null);
|
||||||
_requiresDTLS = false;
|
|
||||||
|
delete _dtlsSession;
|
||||||
|
_dtlsSession = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DomainHandler::initializeDTLSSession() {
|
void DomainHandler::initializeDTLSSession() {
|
||||||
|
@ -122,7 +126,6 @@ void DomainHandler::parseDTLSRequirementPacket(const QByteArray& dtlsRequirement
|
||||||
qDebug() << "domain-server DTLS port changed to" << dtlsPort << "- Enabling DTLS.";
|
qDebug() << "domain-server DTLS port changed to" << dtlsPort << "- Enabling DTLS.";
|
||||||
|
|
||||||
_sockAddr.setPort(dtlsPort);
|
_sockAddr.setPort(dtlsPort);
|
||||||
_requiresDTLS = true;
|
|
||||||
|
|
||||||
initializeDTLSSession();
|
initializeDTLSSession();
|
||||||
}
|
}
|
|
@ -49,6 +49,8 @@ public:
|
||||||
bool isConnected() const { return _isConnected; }
|
bool isConnected() const { return _isConnected; }
|
||||||
void setIsConnected(bool isConnected);
|
void setIsConnected(bool isConnected);
|
||||||
|
|
||||||
|
DTLSClientSession* getDTLSSession() { return _dtlsSession; }
|
||||||
|
|
||||||
void parseDTLSRequirementPacket(const QByteArray& dtlsRequirementPacket);
|
void parseDTLSRequirementPacket(const QByteArray& dtlsRequirementPacket);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
@ -66,7 +68,6 @@ private:
|
||||||
HifiSockAddr _sockAddr;
|
HifiSockAddr _sockAddr;
|
||||||
QUuid _assignmentUUID;
|
QUuid _assignmentUUID;
|
||||||
bool _isConnected;
|
bool _isConnected;
|
||||||
bool _requiresDTLS;
|
|
||||||
DTLSClientSession* _dtlsSession;
|
DTLSClientSession* _dtlsSession;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -50,9 +50,9 @@ HifiSockAddr::HifiSockAddr(const sockaddr* sockaddr) {
|
||||||
_address = QHostAddress(sockaddr);
|
_address = QHostAddress(sockaddr);
|
||||||
|
|
||||||
if (sockaddr->sa_family == AF_INET) {
|
if (sockaddr->sa_family == AF_INET) {
|
||||||
_port = reinterpret_cast<const sockaddr_in*>(sockaddr)->sin_port;
|
_port = ntohs(reinterpret_cast<const sockaddr_in*>(sockaddr)->sin_port);
|
||||||
} else {
|
} else {
|
||||||
_port = reinterpret_cast<const sockaddr_in6*>(sockaddr)->sin6_port;
|
_port = ntohs(reinterpret_cast<const sockaddr_in6*>(sockaddr)->sin6_port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
#include "DomainHandler.h"
|
#include "DomainHandler.h"
|
||||||
#include "Node.h"
|
#include "Node.h"
|
||||||
|
|
||||||
|
const int MAX_PACKET_SIZE = 1500;
|
||||||
|
|
||||||
const quint64 NODE_SILENCE_THRESHOLD_USECS = 2 * 1000 * 1000;
|
const quint64 NODE_SILENCE_THRESHOLD_USECS = 2 * 1000 * 1000;
|
||||||
|
|
||||||
extern const char SOLO_NODE_TYPES[2];
|
extern const char SOLO_NODE_TYPES[2];
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#include <QtCore/QUrl>
|
#include <QtCore/QUrl>
|
||||||
#include <QtNetwork/QHostInfo>
|
#include <QtNetwork/QHostInfo>
|
||||||
|
|
||||||
|
#include <gnutls/dtls.h>
|
||||||
|
|
||||||
#include "AccountManager.h"
|
#include "AccountManager.h"
|
||||||
#include "Assignment.h"
|
#include "Assignment.h"
|
||||||
#include "HifiSockAddr.h"
|
#include "HifiSockAddr.h"
|
||||||
|
@ -318,39 +320,54 @@ void NodeList::sendDomainServerCheckIn() {
|
||||||
// send a STUN request to figure it out
|
// send a STUN request to figure it out
|
||||||
sendSTUNRequest();
|
sendSTUNRequest();
|
||||||
} else if (!_domainHandler.getIP().isNull()) {
|
} else if (!_domainHandler.getIP().isNull()) {
|
||||||
// construct the DS check in packet
|
|
||||||
QUuid packetUUID = (!_sessionUUID.isNull() ? _sessionUUID : _domainHandler.getAssignmentUUID());
|
|
||||||
|
|
||||||
QByteArray domainServerPacket = byteArrayWithPopulatedHeader(PacketTypeDomainListRequest, packetUUID);
|
DTLSClientSession* dtlsSession = _domainHandler.getDTLSSession();
|
||||||
QDataStream packetStream(&domainServerPacket, QIODevice::Append);
|
|
||||||
|
|
||||||
// pack our data to send to the domain-server
|
if (dtlsSession) {
|
||||||
packetStream << _ownerType << _publicSockAddr
|
int handshakeReturn = gnutls_handshake(*dtlsSession->getGnuTLSSession());
|
||||||
<< HifiSockAddr(QHostAddress(getHostOrderLocalAddress()), _nodeSocket.localPort())
|
|
||||||
<< (quint8) _nodeTypesOfInterest.size();
|
|
||||||
|
|
||||||
// copy over the bytes for node types of interest, if required
|
gnutls_handshake_description_t inType = gnutls_handshake_get_last_in(*dtlsSession->getGnuTLSSession());
|
||||||
foreach (NodeType_t nodeTypeOfInterest, _nodeTypesOfInterest) {
|
gnutls_handshake_description_t outType = gnutls_handshake_get_last_out(*dtlsSession->getGnuTLSSession());
|
||||||
packetStream << nodeTypeOfInterest;
|
qDebug() << "in" << gnutls_handshake_description_get_name(inType);
|
||||||
|
qDebug() << "out" << gnutls_handshake_description_get_name(outType);
|
||||||
|
|
||||||
|
// make sure DTLS handshake with the domain-server is complete
|
||||||
|
qDebug() << "GnuTLS handshake return is" << handshakeReturn;
|
||||||
|
} else {
|
||||||
|
// construct the DS check in packet
|
||||||
|
QUuid packetUUID = (!_sessionUUID.isNull() ? _sessionUUID : _domainHandler.getAssignmentUUID());
|
||||||
|
|
||||||
|
QByteArray domainServerPacket = byteArrayWithPopulatedHeader(PacketTypeDomainListRequest, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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++;
|
||||||
}
|
}
|
||||||
|
|
||||||
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++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#include "LimitedNodeList.h"
|
#include "LimitedNodeList.h"
|
||||||
#include "Node.h"
|
#include "Node.h"
|
||||||
|
|
||||||
const quint64 DOMAIN_SERVER_CHECK_IN_USECS = 1 * 1000000;
|
const quint64 DOMAIN_SERVER_CHECK_IN_MSECS = 1 * 1000;
|
||||||
|
|
||||||
const int MAX_SILENT_DOMAIN_SERVER_CHECK_INS = 5;
|
const int MAX_SILENT_DOMAIN_SERVER_CHECK_INS = 5;
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,6 @@ struct xColor {
|
||||||
unsigned char blue;
|
unsigned char blue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static const float ZERO = 0.0f;
|
static const float ZERO = 0.0f;
|
||||||
static const float ONE = 1.0f;
|
static const float ONE = 1.0f;
|
||||||
static const float ONE_HALF = 0.5f;
|
static const float ONE_HALF = 0.5f;
|
||||||
|
@ -66,8 +65,6 @@ static const quint64 USECS_PER_SECOND = USECS_PER_MSEC * MSECS_PER_SECOND;
|
||||||
|
|
||||||
const int BITS_IN_BYTE = 8;
|
const int BITS_IN_BYTE = 8;
|
||||||
|
|
||||||
const int MAX_PACKET_SIZE = 1500;
|
|
||||||
|
|
||||||
quint64 usecTimestamp(const timeval *time);
|
quint64 usecTimestamp(const timeval *time);
|
||||||
quint64 usecTimestampNow();
|
quint64 usecTimestampNow();
|
||||||
void usecTimestampNowForceClockSkew(int clockSkew);
|
void usecTimestampNowForceClockSkew(int clockSkew);
|
||||||
|
|
|
@ -41,7 +41,7 @@ void ThreadedAssignment::commonInit(const QString& targetName, NodeType_t nodeTy
|
||||||
|
|
||||||
QTimer* domainServerTimer = new QTimer(this);
|
QTimer* domainServerTimer = new QTimer(this);
|
||||||
connect(domainServerTimer, SIGNAL(timeout()), this, SLOT(checkInWithDomainServerOrExit()));
|
connect(domainServerTimer, SIGNAL(timeout()), this, SLOT(checkInWithDomainServerOrExit()));
|
||||||
domainServerTimer->start(DOMAIN_SERVER_CHECK_IN_USECS / 1000);
|
domainServerTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS);
|
||||||
|
|
||||||
QTimer* silentNodeRemovalTimer = new QTimer(this);
|
QTimer* silentNodeRemovalTimer = new QTimer(this);
|
||||||
connect(silentNodeRemovalTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes()));
|
connect(silentNodeRemovalTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes()));
|
||||||
|
|
Loading…
Reference in a new issue