diff --git a/libraries/networking/src/udt/ControlSender.cpp b/libraries/networking/src/udt/ControlSender.cpp new file mode 100644 index 0000000000..dd9948502a --- /dev/null +++ b/libraries/networking/src/udt/ControlSender.cpp @@ -0,0 +1,40 @@ +// +// ControlSender.cpp +// libraries/networking/src/udt +// +// Created by Stephen Birarda on 2015-07-27. +// 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 +#include + +#include +#include + +#include "ControlSender.h" + +using namespace udt; + +void ControlSender::loop() { + while (!_isStopped) { + // grab the time now + auto start = std::chrono::high_resolution_clock::now(); + + // for each of the connections managed by the udt::Socket, we need to ask for the ACK value to send + + // since we're infinitely looping, give the thread a chance to process events + QCoreApplication::processEvents(); + + auto end = std::chrono::high_resolution_clock::now(); + + std::chrono::duration elapsed = end - start; + int timeToSleep = _synInterval - (int) elapsed.count(); + + // based on how much time it took us to process, let's figure out how much time we have need to sleep + std::this_thread::sleep_for(std::chrono::microseconds(timeToSleep)); + } +} diff --git a/libraries/networking/src/udt/ControlSender.h b/libraries/networking/src/udt/ControlSender.h new file mode 100644 index 0000000000..040c6a70db --- /dev/null +++ b/libraries/networking/src/udt/ControlSender.h @@ -0,0 +1,39 @@ +// +// ControlSender.h +// libraries/networking/src/udt +// +// Created by Stephen Birarda on 2015-07-27. +// 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 +// + +#pragma once + +#ifndef hifi_ControlSender_h +#define hifi_ControlSender_h + +#include + +namespace udt { + +// Handles the sending of periodic control packets for all active UDT reliable connections +// Currently the interval for all connections is the same, so one thread is sufficient to manage all +class ControlSender : public QObject { + Q_OBJECT +public: + ControlSender(QObject* parent = 0) : QObject(parent) {}; + +public slots: + void loop(); // infinitely loops and sleeps to manage rate of control packet sending + void stop() { _isStopped = true; } // stops the loop + +private: + int _synInterval = 10 * 1000; + bool _isStopped { false }; +}; + +} + +#endif // hifi_ControlSender_h diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index 8bf7f973ae..57c4b75b12 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -11,7 +11,10 @@ #include "Socket.h" +#include + #include "../NetworkLogging.h" +#include "ControlSender.h" #include "Packet.h" using namespace udt; @@ -20,6 +23,38 @@ Socket::Socket(QObject* parent) : QObject(parent) { connect(&_udpSocket, &QUdpSocket::readyRead, this, &Socket::readPendingDatagrams); + + // make a QThread for the ControlSender to live on + QThread* controlThread = new QThread(this); + + // setup the ControlSender and parent it + _controlSender = new ControlSender; + + // move the ControlSender to its thread + _controlSender->moveToThread(controlThread); + + // start the ControlSender once the thread is started + connect(controlThread, &QThread::started, _controlSender, &ControlSender::loop); + + // make sure the control thread is named so we can identify it + controlThread->setObjectName("UDT Control Thread"); + + // start the control thread + controlThread->start(); +} + +Socket::~Socket() { + if (_controlSender) { + QThread* controlThread = _controlSender->thread(); + + // tell the control sender to stop and be deleted so we can wait on its thread + QMetaObject::invokeMethod(_controlSender, "stop"); + _controlSender->deleteLater(); + + // make sure the control thread goes down + controlThread->quit(); + controlThread->wait(); + } } void Socket::rebind() { diff --git a/libraries/networking/src/udt/Socket.h b/libraries/networking/src/udt/Socket.h index 184d8716fe..be6ef982af 100644 --- a/libraries/networking/src/udt/Socket.h +++ b/libraries/networking/src/udt/Socket.h @@ -24,8 +24,9 @@ #include "SeqNum.h" namespace udt { - + class BasePacket; +class ControlSender; class Packet; using PacketFilterOperator = std::function; @@ -37,6 +38,7 @@ class Socket : public QObject { Q_OBJECT public: Socket(QObject* object = 0); + ~Socket(); quint16 localPort() const { return _udpSocket.localPort(); } @@ -68,6 +70,8 @@ private: std::unordered_map _unfilteredHandlers; std::unordered_map _packetSequenceNumbers; + + ControlSender* _controlSender { nullptr }; }; } // namespace udt