examples/network/torrrent: port to QBasicTimer

Instead of using raw timer IDs. QBasicTimer is a value class with
sizeof(int), so not much overhead, and easier to use API. Examples
should show best practices.

Change-Id: I5b9efe47ced69c0067eac891398185be7e87bd0e
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Ahmad Samir 2024-08-30 20:44:29 +03:00
parent 81e3d10ca5
commit 2226581b0b
5 changed files with 37 additions and 55 deletions

View File

@ -22,14 +22,14 @@ static const char ProtocolIdSize = 19;
PeerWireClient::PeerWireClient(const QByteArray &peerId, QObject *parent) PeerWireClient::PeerWireClient(const QByteArray &peerId, QObject *parent)
: QTcpSocket(parent), pendingBlockSizes(0), : QTcpSocket(parent), pendingBlockSizes(0),
pwState(ChokingPeer | ChokedByPeer), receivedHandShake(false), gotPeerId(false), pwState(ChokingPeer | ChokedByPeer), receivedHandShake(false), gotPeerId(false),
sentHandShake(false), nextPacketLength(-1), pendingRequestTimer(0), invalidateTimeout(false), sentHandShake(false), nextPacketLength(-1), invalidateTimeout(false),
keepAliveTimer(0), torrentPeer(nullptr) torrentPeer(nullptr)
{ {
memset(uploadSpeedData, 0, sizeof(uploadSpeedData)); memset(uploadSpeedData, 0, sizeof(uploadSpeedData));
memset(downloadSpeedData, 0, sizeof(downloadSpeedData)); memset(downloadSpeedData, 0, sizeof(downloadSpeedData));
transferSpeedTimer = startTimer(PeerRateControlTimerDelay); transferSpeedTimer.start(PeerRateControlTimerDelay, this);
timeoutTimer = startTimer(ConnectTimeout); timeoutTimer.start(ConnectTimeout, this);
peerIdString = peerId; peerIdString = peerId;
connect(this, &PeerWireClient::readyRead, connect(this, &PeerWireClient::readyRead,
@ -103,8 +103,7 @@ void PeerWireClient::unchokePeer()
write(message, sizeof(message)); write(message, sizeof(message));
pwState &= ~ChokingPeer; pwState &= ~ChokingPeer;
if (pendingRequestTimer) pendingRequestTimer.stop();
killTimer(pendingRequestTimer);
} }
// Sends a "keep-alive" message to prevent the peer from closing // Sends a "keep-alive" message to prevent the peer from closing
@ -126,9 +125,7 @@ void PeerWireClient::sendInterested()
// After telling the peer that we're interested, we expect to get // After telling the peer that we're interested, we expect to get
// unchoked within a certain timeframe; otherwise we'll drop the // unchoked within a certain timeframe; otherwise we'll drop the
// connection. // connection.
if (pendingRequestTimer) pendingRequestTimer.start(PendingRequestTimeout, this);
killTimer(pendingRequestTimer);
pendingRequestTimer = startTimer(PendingRequestTimeout);
} }
// Sends a "not interested" message, informing the peer that it does // Sends a "not interested" message, informing the peer that it does
@ -200,9 +197,7 @@ void PeerWireClient::requestBlock(qint32 piece, qint32 offset, qint32 length)
// After requesting a block, we expect the block to be sent by the // After requesting a block, we expect the block to be sent by the
// other peer within a certain number of seconds. Otherwise, we // other peer within a certain number of seconds. Otherwise, we
// drop the connection. // drop the connection.
if (pendingRequestTimer) pendingRequestTimer.start(PendingRequestTimeout, this);
killTimer(pendingRequestTimer);
pendingRequestTimer = startTimer(PendingRequestTimeout);
} }
// Cancels a request for a block. // Cancels a request for a block.
@ -347,7 +342,7 @@ void PeerWireClient::diconnectFromHost()
void PeerWireClient::timerEvent(QTimerEvent *event) void PeerWireClient::timerEvent(QTimerEvent *event)
{ {
if (event->timerId() == transferSpeedTimer) { if (event->id() == transferSpeedTimer.id()) {
// Rotate the upload / download records. // Rotate the upload / download records.
for (int i = 6; i >= 0; --i) { for (int i = 6; i >= 0; --i) {
uploadSpeedData[i + 1] = uploadSpeedData[i]; uploadSpeedData[i + 1] = uploadSpeedData[i];
@ -355,7 +350,7 @@ void PeerWireClient::timerEvent(QTimerEvent *event)
} }
uploadSpeedData[0] = 0; uploadSpeedData[0] = 0;
downloadSpeedData[0] = 0; downloadSpeedData[0] = 0;
} else if (event->timerId() == timeoutTimer) { } else if (event->id() == timeoutTimer.id()) {
// Disconnect if we timed out; otherwise the timeout is // Disconnect if we timed out; otherwise the timeout is
// restarted. // restarted.
if (invalidateTimeout) { if (invalidateTimeout) {
@ -364,9 +359,9 @@ void PeerWireClient::timerEvent(QTimerEvent *event)
abort(); abort();
emit infoHashReceived(QByteArray()); emit infoHashReceived(QByteArray());
} }
} else if (event->timerId() == pendingRequestTimer) { } else if (event->id() == pendingRequestTimer.id()) {
abort(); abort();
} else if (event->timerId() == keepAliveTimer) { } else if (event->id() == keepAliveTimer.id()) {
sendKeepAlive(); sendKeepAlive();
} }
QTcpSocket::timerEvent(event); QTcpSocket::timerEvent(event);
@ -378,9 +373,7 @@ void PeerWireClient::sendHandShake()
sentHandShake = true; sentHandShake = true;
// Restart the timeout // Restart the timeout
if (timeoutTimer) timeoutTimer.start(ClientTimeout, this);
killTimer(timeoutTimer);
timeoutTimer = startTimer(ClientTimeout);
// Write the 68 byte PeerWire handshake. // Write the 68 byte PeerWire handshake.
write(&ProtocolIdSize, 1); write(&ProtocolIdSize, 1);
@ -440,8 +433,8 @@ void PeerWireClient::processIncomingData()
} }
// Initialize keep-alive timer // Initialize keep-alive timer
if (!keepAliveTimer) if (!keepAliveTimer.isActive())
keepAliveTimer = startTimer(KeepAliveInterval); keepAliveTimer.start(KeepAliveInterval, this);
do { do {
// Find the packet length // Find the packet length
@ -482,8 +475,7 @@ void PeerWireClient::processIncomingData()
// We have been choked. // We have been choked.
pwState |= ChokedByPeer; pwState |= ChokedByPeer;
incoming.clear(); incoming.clear();
if (pendingRequestTimer) pendingRequestTimer.stop();
killTimer(pendingRequestTimer);
emit choked(); emit choked();
break; break;
case UnchokePacket: case UnchokePacket:
@ -546,11 +538,8 @@ void PeerWireClient::processIncomingData()
// The peer sends a block. // The peer sends a block.
emit blockReceived(index, begin, packet.mid(9)); emit blockReceived(index, begin, packet.mid(9));
// Kill the pending block timer. // Stop the pending block timer.
if (pendingRequestTimer) { pendingRequestTimer.stop();
killTimer(pendingRequestTimer);
pendingRequestTimer = 0;
}
break; break;
} }
case CancelPacket: { case CancelPacket: {

View File

@ -4,6 +4,7 @@
#ifndef PEERWIRECLIENT_H #ifndef PEERWIRECLIENT_H
#define PEERWIRECLIENT_H #define PEERWIRECLIENT_H
#include <QBasicTimer>
#include <QBitArray> #include <QBitArray>
#include <QList> #include <QList>
#include <QTcpSocket> #include <QTcpSocket>
@ -150,13 +151,13 @@ private:
// Upload/download speed records // Upload/download speed records
qint64 uploadSpeedData[8]; qint64 uploadSpeedData[8];
qint64 downloadSpeedData[8]; qint64 downloadSpeedData[8];
int transferSpeedTimer; QBasicTimer transferSpeedTimer;
// Timeout handling // Timeout handling
int timeoutTimer; QBasicTimer timeoutTimer;
int pendingRequestTimer; QBasicTimer pendingRequestTimer;
bool invalidateTimeout; bool invalidateTimeout;
int keepAliveTimer; QBasicTimer keepAliveTimer;
// Checksum, peer ID and set of available pieces // Checksum, peer ID and set of available pieces
QByteArray infoHash; QByteArray infoHash;

View File

@ -67,7 +67,7 @@ public:
void callScheduler(); void callScheduler();
bool connectingToClients; bool connectingToClients;
void callPeerConnector(); void callPeerConnector();
int uploadScheduleTimer; QBasicTimer uploadScheduleTimer;
// Pieces // Pieces
QMap<qint32, PeerWireClient *> readIds; QMap<qint32, PeerWireClient *> readIds;
@ -83,7 +83,7 @@ public:
qint64 uploadedBytes; qint64 uploadedBytes;
int downloadRate[RateControlWindowLength]; int downloadRate[RateControlWindowLength];
int uploadRate[RateControlWindowLength]; int uploadRate[RateControlWindowLength];
int transferRateTimer; QBasicTimer transferRateTimer;
TorrentClient *q; TorrentClient *q;
}; };
@ -97,14 +97,12 @@ TorrentClientPrivate::TorrentClientPrivate(TorrentClient *qq)
stateString = QT_TRANSLATE_NOOP(TorrentClient, "Idle"); stateString = QT_TRANSLATE_NOOP(TorrentClient, "Idle");
schedulerCalled = false; schedulerCalled = false;
connectingToClients = false; connectingToClients = false;
uploadScheduleTimer = 0;
lastProgressValue = -1; lastProgressValue = -1;
pieceCount = 0; pieceCount = 0;
downloadedBytes = 0; downloadedBytes = 0;
uploadedBytes = 0; uploadedBytes = 0;
memset(downloadRate, 0, sizeof(downloadRate)); memset(downloadRate, 0, sizeof(downloadRate));
memset(uploadRate, 0, sizeof(uploadRate)); memset(uploadRate, 0, sizeof(uploadRate));
transferRateTimer = 0;
} }
void TorrentClientPrivate::setError(TorrentClient::Error errorCode) void TorrentClientPrivate::setError(TorrentClient::Error errorCode)
@ -414,11 +412,7 @@ void TorrentClient::stop()
State oldState = d->state; State oldState = d->state;
d->setState(Stopping); d->setState(Stopping);
// Stop the timer d->transferRateTimer.stop();
if (d->transferRateTimer) {
killTimer(d->transferRateTimer);
d->transferRateTimer = 0;
}
// Abort all existing connections // Abort all existing connections
for (PeerWireClient *client : std::as_const(d->connections)) { for (PeerWireClient *client : std::as_const(d->connections)) {
@ -461,13 +455,13 @@ void TorrentClient::setPaused(bool paused)
void TorrentClient::timerEvent(QTimerEvent *event) void TorrentClient::timerEvent(QTimerEvent *event)
{ {
if (event->timerId() == d->uploadScheduleTimer) { if (event->id() == d->uploadScheduleTimer.id()) {
// Update the state of who's choked and who's not // Update the state of who's choked and who's not
scheduleUploads(); scheduleUploads();
return; return;
} }
if (event->timerId() != d->transferRateTimer) { if (event->id() != d->transferRateTimer.id()) {
QObject::timerEvent(event); QObject::timerEvent(event);
return; return;
} }
@ -492,8 +486,7 @@ void TorrentClient::timerEvent(QTimerEvent *event)
// Stop the timer if there is no activity. // Stop the timer if there is no activity.
if (downloadBytesPerSecond == 0 && uploadBytesPerSecond == 0) { if (downloadBytesPerSecond == 0 && uploadBytesPerSecond == 0) {
killTimer(d->transferRateTimer); d->transferRateTimer.stop();
d->transferRateTimer = 0;
} }
} }
@ -534,7 +527,7 @@ void TorrentClient::fullVerificationDone()
++it; ++it;
} }
d->uploadScheduleTimer = startTimer(UploadScheduleInterval); d->uploadScheduleTimer.start(UploadScheduleInterval, this);
// Start the server // Start the server
TorrentServer *server = TorrentServer::instance(); TorrentServer *server = TorrentServer::instance();
@ -1009,8 +1002,8 @@ void TorrentClient::blockReceived(qint32 pieceIndex, qint32 begin, const QByteAr
void TorrentClient::peerWireBytesWritten(qint64 size) void TorrentClient::peerWireBytesWritten(qint64 size)
{ {
if (!d->transferRateTimer) if (!d->transferRateTimer.isActive())
d->transferRateTimer = startTimer(RateControlTimerDelay); d->transferRateTimer.start(RateControlTimerDelay, this);
d->uploadRate[0] += size; d->uploadRate[0] += size;
d->uploadedBytes += size; d->uploadedBytes += size;
@ -1019,8 +1012,8 @@ void TorrentClient::peerWireBytesWritten(qint64 size)
void TorrentClient::peerWireBytesReceived(qint64 size) void TorrentClient::peerWireBytesReceived(qint64 size)
{ {
if (!d->transferRateTimer) if (!d->transferRateTimer.isActive())
d->transferRateTimer = startTimer(RateControlTimerDelay); d->transferRateTimer.start(RateControlTimerDelay, this);
d->downloadRate[0] += size; d->downloadRate[0] += size;
d->downloadedBytes += size; d->downloadedBytes += size;

View File

@ -45,7 +45,7 @@ void TrackerClient::stop()
void TrackerClient::timerEvent(QTimerEvent *event) void TrackerClient::timerEvent(QTimerEvent *event)
{ {
if (event->timerId() == requestIntervalTimer) { if (event->id() == requestIntervalTimer.id()) {
fetchPeerList(); fetchPeerList();
} else { } else {
QObject::timerEvent(event); QObject::timerEvent(event);
@ -151,9 +151,7 @@ void TrackerClient::httpRequestDone(QNetworkReply *reply)
if (dict.contains("interval")) { if (dict.contains("interval")) {
// Mandatory item // Mandatory item
if (requestIntervalTimer != -1) requestIntervalTimer.start(std::chrono::seconds(dict.value("interval").toInt()), this);
killTimer(requestIntervalTimer);
requestIntervalTimer = startTimer(std::chrono::seconds(dict.value("interval").toInt()));
} }
if (dict.contains("peers")) { if (dict.contains("peers")) {

View File

@ -4,6 +4,7 @@
#ifndef TRACKERCLIENT_H #ifndef TRACKERCLIENT_H
#define TRACKERCLIENT_H #define TRACKERCLIENT_H
#include <QBasicTimer>
#include <QByteArray> #include <QByteArray>
#include <QList> #include <QList>
#include <QObject> #include <QObject>
@ -51,7 +52,7 @@ private slots:
private: private:
TorrentClient *torrentDownloader; TorrentClient *torrentDownloader;
int requestIntervalTimer = -1; QBasicTimer requestIntervalTimer;
QNetworkAccessManager http; QNetworkAccessManager http;
MetaInfo metaInfo; MetaInfo metaInfo;
QByteArray trackerId; QByteArray trackerId;