mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-15 17:46:47 +02:00
complete check in and heartbeat via DTLS
This commit is contained in:
parent
7b6ce77690
commit
efd176f93c
8 changed files with 76 additions and 19 deletions
|
@ -483,6 +483,9 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
|
|||
LimitedNodeList* nodeList = LimitedNodeList::getInstance();
|
||||
|
||||
if (nodeInterestList.size() > 0) {
|
||||
|
||||
DTLSServerSession* dtlsSession = _isUsingDTLS ? _dtlsSessions[senderSockAddr] : NULL;
|
||||
|
||||
// if the node has any interest types, send back those nodes as well
|
||||
foreach (const SharedNodePointer& otherNode, nodeList->getNodeHash()) {
|
||||
|
||||
|
@ -516,7 +519,11 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
|
|||
// we need to break here and start a new packet
|
||||
// so send the current one
|
||||
|
||||
nodeList->writeDatagram(broadcastPacket, node, senderSockAddr);
|
||||
if (!dtlsSession) {
|
||||
nodeList->writeDatagram(broadcastPacket, node, senderSockAddr);
|
||||
} else {
|
||||
dtlsSession->writeDatagram(broadcastPacket);
|
||||
}
|
||||
|
||||
// reset the broadcastPacket structure
|
||||
broadcastPacket.resize(numBroadcastPacketLeadBytes);
|
||||
|
@ -527,10 +534,14 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
|
|||
broadcastPacket.append(nodeByteArray);
|
||||
}
|
||||
}
|
||||
|
||||
// always write the last broadcastPacket
|
||||
if (!dtlsSession) {
|
||||
nodeList->writeDatagram(broadcastPacket, node, senderSockAddr);
|
||||
} else {
|
||||
dtlsSession->writeDatagram(broadcastPacket);
|
||||
}
|
||||
}
|
||||
|
||||
// always write the last broadcastPacket
|
||||
nodeList->writeDatagram(broadcastPacket, node, senderSockAddr);
|
||||
}
|
||||
|
||||
void DomainServer::readAvailableDatagrams() {
|
||||
|
@ -640,12 +651,12 @@ void DomainServer::readAvailableDTLSDatagrams() {
|
|||
}
|
||||
} else {
|
||||
// pull the data from this user off the stack and process it
|
||||
int receiveCode = gnutls_record_recv(*existingSession->getGnuTLSSession(),
|
||||
peekDatagram.data(), peekDatagram.size());
|
||||
if (receiveCode > 0) {
|
||||
processDatagram(peekDatagram, senderHifiSockAddr);
|
||||
} else if (gnutls_error_is_fatal(receiveCode)) {
|
||||
qDebug() << "Fatal error -" << gnutls_strerror(receiveCode) << "- during DTLS handshake with"
|
||||
int receivedBytes = gnutls_record_recv(*existingSession->getGnuTLSSession(),
|
||||
peekDatagram.data(), peekDatagram.size());
|
||||
if (receivedBytes > 0) {
|
||||
processDatagram(peekDatagram.left(receivedBytes), senderHifiSockAddr);
|
||||
} else if (gnutls_error_is_fatal(receivedBytes)) {
|
||||
qDebug() << "Fatal error -" << gnutls_strerror(receivedBytes) << "- during DTLS handshake with"
|
||||
<< senderHifiSockAddr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include "NodeList.h"
|
||||
#include "DTLSSession.h"
|
||||
|
||||
#define DTLS_VERBOSE_DEBUG 0
|
||||
|
||||
int DTLSSession::socketPullTimeout(gnutls_transport_ptr_t ptr, unsigned int ms) {
|
||||
DTLSSession* session = static_cast<DTLSSession*>(ptr);
|
||||
QUdpSocket& dtlsSocket = session->_dtlsSocket;
|
||||
|
@ -47,14 +49,19 @@ ssize_t DTLSSession::socketPull(gnutls_transport_ptr_t ptr, void* buffer, size_t
|
|||
pulledSockAddr.getAddressPointer(), pulledSockAddr.getPortPointer());
|
||||
if (bytesReceived == -1) {
|
||||
// no data to pull, return -1
|
||||
#if DTLS_VERBOSE_DEBUG
|
||||
qDebug() << "Received no data on call to readDatagram";
|
||||
#endif
|
||||
return bytesReceived;
|
||||
}
|
||||
|
||||
if (pulledSockAddr == session->_destinationSocket) {
|
||||
// bytes received from the correct sender, return number of bytes received
|
||||
|
||||
#if DTLS_VERBOSE_DEBUG
|
||||
qDebug() << "Received" << bytesReceived << "on DTLS socket from" << pulledSockAddr;
|
||||
qDebug() << QByteArray(reinterpret_cast<char*>(buffer), bytesReceived).toHex();
|
||||
#endif
|
||||
|
||||
return bytesReceived;
|
||||
}
|
||||
|
||||
|
@ -69,8 +76,10 @@ ssize_t DTLSSession::socketPush(gnutls_transport_ptr_t ptr, const void* buffer,
|
|||
DTLSSession* session = static_cast<DTLSSession*>(ptr);
|
||||
QUdpSocket& dtlsSocket = session->_dtlsSocket;
|
||||
|
||||
#if DTLS_VERBOSE_DEBUG
|
||||
qDebug() << "Pushing a message of size" << size << "to" << session->_destinationSocket;
|
||||
qDebug() << QByteArray(reinterpret_cast<const char*>(buffer), size).toHex();
|
||||
#endif
|
||||
|
||||
return dtlsSocket.writeDatagram(reinterpret_cast<const char*>(buffer), size,
|
||||
session->_destinationSocket.getAddress(), session->_destinationSocket.getPort());
|
||||
}
|
||||
|
@ -93,4 +102,9 @@ DTLSSession::DTLSSession(int end, QUdpSocket& dtlsSocket, HifiSockAddr& destinat
|
|||
gnutls_transport_set_push_function(_gnutlsSession, socketPush);
|
||||
gnutls_transport_set_pull_function(_gnutlsSession, socketPull);
|
||||
gnutls_transport_set_pull_timeout_function(_gnutlsSession, socketPullTimeout);
|
||||
}
|
||||
|
||||
qint64 DTLSSession::writeDatagram(const QByteArray& datagram) {
|
||||
// we don't need to put a hash in this packet, so just send it off
|
||||
return gnutls_record_send(_gnutlsSession, datagram.data(), datagram.size());
|
||||
}
|
|
@ -24,6 +24,8 @@ public:
|
|||
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);
|
||||
|
||||
qint64 writeDatagram(const QByteArray& datagram);
|
||||
|
||||
gnutls_session_t* getGnuTLSSession() { return &_gnutlsSession; }
|
||||
|
||||
bool completedHandshake() const { return _completedHandshake; }
|
||||
|
|
|
@ -115,8 +115,6 @@ void DomainHandler::setHostname(const QString& hostname) {
|
|||
void DomainHandler::completeDTLSHandshake() {
|
||||
int handshakeReturn = gnutls_handshake(*_dtlsSession->getGnuTLSSession());
|
||||
|
||||
qDebug() << "handshake return is" << handshakeReturn;
|
||||
|
||||
if (handshakeReturn == 0) {
|
||||
// we've shaken hands, so we're good to go now
|
||||
_dtlsSession->setCompletedHandshake(true);
|
||||
|
@ -125,6 +123,9 @@ void DomainHandler::completeDTLSHandshake() {
|
|||
delete _handshakeTimer;
|
||||
_handshakeTimer = NULL;
|
||||
|
||||
// emit a signal so NodeList can handle incoming DTLS packets
|
||||
emit completedDTLSHandshake();
|
||||
|
||||
} else if (gnutls_error_is_fatal(handshakeReturn)) {
|
||||
// this was a fatal error handshaking, so remove this session
|
||||
qDebug() << "Fatal error -" << gnutls_strerror(handshakeReturn)
|
||||
|
|
|
@ -60,7 +60,8 @@ private slots:
|
|||
signals:
|
||||
void hostnameChanged(const QString& hostname);
|
||||
void connectedToDomain(const QString& hostname);
|
||||
void initializedDTLSSession();
|
||||
void completedDTLSHandshake();
|
||||
|
||||
private:
|
||||
void reset();
|
||||
void initializeDTLSSession();
|
||||
|
|
|
@ -173,7 +173,7 @@ bool LimitedNodeList::packetVersionAndHashMatch(const QByteArray& packet) {
|
|||
}
|
||||
|
||||
qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr,
|
||||
const QUuid& connectionSecret) {
|
||||
const QUuid& connectionSecret) {
|
||||
QByteArray datagramCopy = datagram;
|
||||
|
||||
if (!connectionSecret.isNull()) {
|
||||
|
|
|
@ -65,6 +65,9 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned
|
|||
|
||||
// clear our NodeList when logout is requested
|
||||
connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset);
|
||||
|
||||
// perform a function when DTLS handshake is completed
|
||||
connect(&_domainHandler, &DomainHandler::completedDTLSHandshake, this, &NodeList::completedDTLSHandshake);
|
||||
}
|
||||
|
||||
qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) {
|
||||
|
@ -111,6 +114,28 @@ void NodeList::timePingReply(const QByteArray& packet, const SharedNodePointer&
|
|||
}
|
||||
}
|
||||
|
||||
void NodeList::completedDTLSHandshake() {
|
||||
// at this point, we've got a DTLS socket
|
||||
// make this NodeList the handler of DTLS packets
|
||||
connect(_dtlsSocket, &QUdpSocket::readyRead, this, &NodeList::processAvailableDTLSDatagrams);
|
||||
}
|
||||
|
||||
void NodeList::processAvailableDTLSDatagrams() {
|
||||
while (_dtlsSocket->hasPendingDatagrams()) {
|
||||
QByteArray dtlsPacket(_dtlsSocket->pendingDatagramSize(), 0);
|
||||
|
||||
// pull the data from this user off the stack and process it
|
||||
int receivedBytes = gnutls_record_recv(*_domainHandler.getDTLSSession()->getGnuTLSSession(),
|
||||
dtlsPacket.data(), dtlsPacket.size());
|
||||
if (receivedBytes > 0) {
|
||||
// successful data receive, hand this off to processNodeData
|
||||
processNodeData(_domainHandler.getSockAddr(), dtlsPacket.left(receivedBytes));
|
||||
} else if (gnutls_error_is_fatal(receivedBytes)) {
|
||||
qDebug() << "Fatal error -" << gnutls_strerror(receivedBytes) << "- receiving DTLS packet from domain-server.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet) {
|
||||
switch (packetTypeForPacket(packet)) {
|
||||
case PacketTypeDomainList: {
|
||||
|
@ -342,8 +367,8 @@ void NodeList::sendDomainServerCheckIn() {
|
|||
|
||||
// pack our data to send to the domain-server
|
||||
packetStream << _ownerType << _publicSockAddr
|
||||
<< HifiSockAddr(QHostAddress(getHostOrderLocalAddress()), _nodeSocket.localPort())
|
||||
<< (quint8) _nodeTypesOfInterest.size();
|
||||
<< HifiSockAddr(QHostAddress(getHostOrderLocalAddress()), _nodeSocket.localPort())
|
||||
<< (quint8) _nodeTypesOfInterest.size();
|
||||
|
||||
// copy over the bytes for node types of interest, if required
|
||||
foreach (NodeType_t nodeTypeOfInterest, _nodeTypesOfInterest) {
|
||||
|
@ -353,7 +378,7 @@ void NodeList::sendDomainServerCheckIn() {
|
|||
if (!isUsingDTLS) {
|
||||
writeDatagram(domainServerPacket, _domainHandler.getSockAddr(), QUuid());
|
||||
} else {
|
||||
gnutls_record_send(*dtlsSession->getGnuTLSSession(), domainServerPacket.data(), domainServerPacket.size());
|
||||
dtlsSession->writeDatagram(domainServerPacket);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ public:
|
|||
void resetNodeInterestSet() { _nodeTypesOfInterest.clear(); }
|
||||
|
||||
void processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet);
|
||||
|
||||
int processDomainServerList(const QByteArray& packet);
|
||||
|
||||
void setAssignmentServerSocket(const HifiSockAddr& serverSocket) { _assignmentServerSocket = serverSocket; }
|
||||
|
@ -82,6 +83,8 @@ public slots:
|
|||
void reset();
|
||||
void sendDomainServerCheckIn();
|
||||
void pingInactiveNodes();
|
||||
void completedDTLSHandshake();
|
||||
void processAvailableDTLSDatagrams();
|
||||
signals:
|
||||
void limitOfSilentDomainCheckInsReached();
|
||||
private:
|
||||
|
|
Loading…
Reference in a new issue