1
0
mirror of https://github.com/d47081/qBittorrent.git synced 2025-01-10 23:07:59 +00:00

Merge pull request #9953 from Chocobo1/announce

Use ip parameter from tracker request if provided
This commit is contained in:
Mike Tzou 2018-12-05 11:13:03 +08:00 committed by GitHub
commit eb957bb790
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 36 deletions

View File

@ -60,7 +60,7 @@ bool Peer::operator==(const Peer &other) const
QString Peer::uid() const QString Peer::uid() const
{ {
return ip + ':' + QString::number(port); return ip.toString() + ':' + QString::number(port);
} }
libtorrent::entry Peer::toEntry(bool noPeerId) const libtorrent::entry Peer::toEntry(bool noPeerId) const
@ -68,7 +68,7 @@ libtorrent::entry Peer::toEntry(bool noPeerId) const
libtorrent::entry::dictionary_type peerMap; libtorrent::entry::dictionary_type peerMap;
if (!noPeerId) if (!noPeerId)
peerMap["id"] = libtorrent::entry(peerId.toStdString()); peerMap["id"] = libtorrent::entry(peerId.toStdString());
peerMap["ip"] = libtorrent::entry(ip.toStdString()); peerMap["ip"] = libtorrent::entry(ip.toString().toStdString());
peerMap["port"] = libtorrent::entry(port); peerMap["port"] = libtorrent::entry(port);
return libtorrent::entry(peerMap); return libtorrent::entry(peerMap);
@ -145,10 +145,12 @@ void Tracker::respondToAnnounceRequest()
queryParams[paramName] = paramValue; queryParams[paramName] = paramValue;
} }
TrackerAnnounceRequest annonceReq; TrackerAnnounceRequest announceReq;
// IP // IP
annonceReq.peer.ip = m_env.clientAddress.toString(); // Use the "ip" parameter provided from tracker request first, then fall back to client IP if invalid
const QHostAddress paramIP {QString::fromLatin1(queryParams.value("ip"))};
announceReq.peer.ip = paramIP.isNull() ? m_env.clientAddress : paramIP;
// 1. Get info_hash // 1. Get info_hash
if (!queryParams.contains("info_hash")) { if (!queryParams.contains("info_hash")) {
@ -156,7 +158,7 @@ void Tracker::respondToAnnounceRequest()
status(101, "Missing info_hash"); status(101, "Missing info_hash");
return; return;
} }
annonceReq.infoHash = queryParams.value("info_hash"); announceReq.infoHash = queryParams.value("info_hash");
// info_hash cannot be longer than 20 bytes // info_hash cannot be longer than 20 bytes
/*if (annonce_req.info_hash.toLatin1().length() > 20) { /*if (annonce_req.info_hash.toLatin1().length() > 20) {
qDebug("Tracker: Info_hash is not 20 byte long: %s (%d)", qUtf8Printable(annonce_req.info_hash), annonce_req.info_hash.toLatin1().length()); qDebug("Tracker: Info_hash is not 20 byte long: %s (%d)", qUtf8Printable(annonce_req.info_hash), annonce_req.info_hash.toLatin1().length());
@ -170,7 +172,7 @@ void Tracker::respondToAnnounceRequest()
status(102, "Missing peer_id"); status(102, "Missing peer_id");
return; return;
} }
annonceReq.peer.peerId = queryParams.value("peer_id"); announceReq.peer.peerId = queryParams.value("peer_id");
// peer_id cannot be longer than 20 bytes // peer_id cannot be longer than 20 bytes
/*if (annonce_req.peer.peer_id.length() > 20) { /*if (annonce_req.peer.peer_id.length() > 20) {
qDebug("Tracker: peer_id is not 20 byte long: %s", qUtf8Printable(annonce_req.peer.peer_id)); qDebug("Tracker: peer_id is not 20 byte long: %s", qUtf8Printable(annonce_req.peer.peer_id));
@ -185,52 +187,52 @@ void Tracker::respondToAnnounceRequest()
return; return;
} }
bool ok = false; bool ok = false;
annonceReq.peer.port = queryParams.value("port").toInt(&ok); announceReq.peer.port = queryParams.value("port").toInt(&ok);
if (!ok || (annonceReq.peer.port < 0) || (annonceReq.peer.port > 65535)) { if (!ok || (announceReq.peer.port < 0) || (announceReq.peer.port > 65535)) {
qDebug("Tracker: Invalid port number (%d)", annonceReq.peer.port); qDebug("Tracker: Invalid port number (%d)", announceReq.peer.port);
status(103, "Missing port"); status(103, "Missing port");
return; return;
} }
// 4. Get event // 4. Get event
annonceReq.event = ""; announceReq.event = "";
if (queryParams.contains("event")) { if (queryParams.contains("event")) {
annonceReq.event = queryParams.value("event"); announceReq.event = queryParams.value("event");
qDebug("Tracker: event is %s", qUtf8Printable(annonceReq.event)); qDebug("Tracker: event is %s", qUtf8Printable(announceReq.event));
} }
// 5. Get numwant // 5. Get numwant
annonceReq.numwant = 50; announceReq.numwant = 50;
if (queryParams.contains("numwant")) { if (queryParams.contains("numwant")) {
int tmp = queryParams.value("numwant").toInt(); int tmp = queryParams.value("numwant").toInt();
if (tmp > 0) { if (tmp > 0) {
qDebug("Tracker: numwant = %d", tmp); qDebug("Tracker: numwant = %d", tmp);
annonceReq.numwant = tmp; announceReq.numwant = tmp;
} }
} }
// 6. no_peer_id (extension) // 6. no_peer_id (extension)
annonceReq.noPeerId = false; announceReq.noPeerId = false;
if (queryParams.contains("no_peer_id")) if (queryParams.contains("no_peer_id"))
annonceReq.noPeerId = true; announceReq.noPeerId = true;
// 7. TODO: support "compact" extension // 7. TODO: support "compact" extension
// Done parsing, now let's reply // Done parsing, now let's reply
if (annonceReq.event == "stopped") { if (announceReq.event == "stopped") {
unregisterPeer(annonceReq); unregisterPeer(announceReq);
} }
else { else {
registerPeer(annonceReq); registerPeer(announceReq);
replyWithPeerList(annonceReq); replyWithPeerList(announceReq);
} }
} }
void Tracker::registerPeer(const TrackerAnnounceRequest &annonceReq) void Tracker::registerPeer(const TrackerAnnounceRequest &announceReq)
{ {
if (annonceReq.peer.port == 0) return; if (announceReq.peer.port == 0) return;
if (!m_torrents.contains(annonceReq.infoHash)) { if (!m_torrents.contains(announceReq.infoHash)) {
// Unknown torrent // Unknown torrent
if (m_torrents.size() == MAX_TORRENTS) { if (m_torrents.size() == MAX_TORRENTS) {
// Reached max size, remove a random torrent // Reached max size, remove a random torrent
@ -239,34 +241,34 @@ void Tracker::registerPeer(const TrackerAnnounceRequest &annonceReq)
} }
// Register the user // Register the user
PeerList &peers = m_torrents[annonceReq.infoHash]; PeerList &peers = m_torrents[announceReq.infoHash];
if (!peers.contains(annonceReq.peer.uid())) { if (!peers.contains(announceReq.peer.uid())) {
// Unknown peer // Unknown peer
if (peers.size() == MAX_PEERS_PER_TORRENT) { if (peers.size() == MAX_PEERS_PER_TORRENT) {
// Too many peers, remove a random one // Too many peers, remove a random one
peers.erase(peers.begin()); peers.erase(peers.begin());
} }
} }
peers[annonceReq.peer.uid()] = annonceReq.peer; peers[announceReq.peer.uid()] = announceReq.peer;
} }
void Tracker::unregisterPeer(const TrackerAnnounceRequest &annonceReq) void Tracker::unregisterPeer(const TrackerAnnounceRequest &announceReq)
{ {
if (annonceReq.peer.port == 0) return; if (announceReq.peer.port == 0) return;
if (m_torrents[annonceReq.infoHash].remove(annonceReq.peer.uid()) > 0) if (m_torrents[announceReq.infoHash].remove(announceReq.peer.uid()) > 0)
qDebug("Tracker: Peer stopped downloading, deleting it from the list"); qDebug("Tracker: Peer stopped downloading, deleting it from the list");
} }
void Tracker::replyWithPeerList(const TrackerAnnounceRequest &annonceReq) void Tracker::replyWithPeerList(const TrackerAnnounceRequest &announceReq)
{ {
// Prepare the entry for bencoding // Prepare the entry for bencoding
libtorrent::entry::dictionary_type replyDict; libtorrent::entry::dictionary_type replyDict;
replyDict["interval"] = libtorrent::entry(ANNOUNCE_INTERVAL); replyDict["interval"] = libtorrent::entry(ANNOUNCE_INTERVAL);
libtorrent::entry::list_type peerList; libtorrent::entry::list_type peerList;
for (const Peer &p : m_torrents.value(annonceReq.infoHash)) for (const Peer &p : m_torrents.value(announceReq.infoHash))
peerList.push_back(p.toEntry(annonceReq.noPeerId)); peerList.push_back(p.toEntry(announceReq.noPeerId));
replyDict["peers"] = libtorrent::entry(peerList); replyDict["peers"] = libtorrent::entry(peerList);
const libtorrent::entry replyEntry(replyDict); const libtorrent::entry replyEntry(replyDict);

View File

@ -32,6 +32,7 @@
#include <QHash> #include <QHash>
#include <QObject> #include <QObject>
#include <QHostAddress>
#include "base/http/irequesthandler.h" #include "base/http/irequesthandler.h"
#include "base/http/responsebuilder.h" #include "base/http/responsebuilder.h"
@ -51,7 +52,7 @@ namespace BitTorrent
{ {
struct Peer struct Peer
{ {
QString ip; QHostAddress ip;
QByteArray peerId; QByteArray peerId;
int port; int port;
@ -90,9 +91,9 @@ namespace BitTorrent
private: private:
void respondToAnnounceRequest(); void respondToAnnounceRequest();
void registerPeer(const TrackerAnnounceRequest &annonceReq); void registerPeer(const TrackerAnnounceRequest &announceReq);
void unregisterPeer(const TrackerAnnounceRequest &annonceReq); void unregisterPeer(const TrackerAnnounceRequest &announceReq);
void replyWithPeerList(const TrackerAnnounceRequest &annonceReq); void replyWithPeerList(const TrackerAnnounceRequest &announceReq);
Http::Server *m_server; Http::Server *m_server;
TorrentList m_torrents; TorrentList m_torrents;