diff --git a/src/dht/announcereq.h b/src/dht/announcereq.h --- a/src/dht/announcereq.h +++ b/src/dht/announcereq.h @@ -34,21 +34,21 @@ { public: AnnounceReq(); - AnnounceReq(const Key & id,const Key & info_hash,bt::Uint16 port,const Key & token); + AnnounceReq(const Key & id,const Key & info_hash,bt::Uint16 port,const QByteArray & token); ~AnnounceReq() override; void apply(DHT* dh_table) override; void print() override; void encode(QByteArray & arr) const override; void parse(bt::BDictNode* dict) override; - const Key & getToken() const {return token;} + const QByteArray & getToken() const {return token;} bt::Uint16 getPort() const {return port;} typedef QSharedPointer Ptr; private: bt::Uint16 port; - Key token; + QByteArray token; }; } diff --git a/src/dht/announcereq.cpp b/src/dht/announcereq.cpp --- a/src/dht/announcereq.cpp +++ b/src/dht/announcereq.cpp @@ -35,7 +35,7 @@ method = dht::ANNOUNCE_PEER; } - AnnounceReq::AnnounceReq(const Key & id, const Key & info_hash, Uint16 port, const Key & token) + AnnounceReq::AnnounceReq(const Key & id, const Key & info_hash, Uint16 port, const QByteArray & token) : GetPeersReq(id, info_hash), port(port), token(token) { method = dht::ANNOUNCE_PEER; @@ -48,11 +48,33 @@ dh_table->announce(*this); } + QString tokenToHex(const QByteArray &token) + { + // slightly modified implementation of QByteArray::ToHex() (since Qt 5.9) + // copied here to keep minimal Qt ver. requirement eq. to 5.7 + QByteArray hex(token.size() * 2, Qt::Uninitialized); + char *hexData = hex.data(); + const uchar *data = (const uchar *)token.data(); + for (int i = 0; i < token.size(); ++i) { + int j = (data[i] >> 4) & 0xf; + if (j <= 9) + hexData[i*2] = (j + '0'); + else + hexData[i*2] = (j + 'A' - 10); // <- use upper case + j = data[i] & 0xf; + if (j <= 9) + hexData[i*2+1] = (j + '0'); + else + hexData[i*2+1] = (j + 'A' - 10); + } + return QString(hex); + } + void AnnounceReq::print() { Out(SYS_DHT | LOG_DEBUG) << QString("REQ: %1 %2 : announce_peer %3 %4 %5") .arg(mtid[0]).arg(id.toString()).arg(info_hash.toString()) - .arg(port).arg(token.toString()) << endl; + .arg(port).arg(tokenToHex(token)) << endl; } void AnnounceReq::encode(QByteArray & arr) const @@ -65,7 +87,8 @@ enc.write(QByteArrayLiteral("id")); enc.write(id.getData(), 20); enc.write(QByteArrayLiteral("info_hash")); enc.write(info_hash.getData(), 20); enc.write(QByteArrayLiteral("port")); enc.write((Uint32)port); - enc.write(QByteArrayLiteral("token")); enc.write(token.getData(), 20); + // must cast data() to (const Uint8*) to call right write() overload + enc.write(QByteArrayLiteral("token")); enc.write((const Uint8*)token.data(), token.size()); } enc.end(); enc.write(REQ); enc.write(QByteArrayLiteral("announce_peer")); @@ -84,7 +107,7 @@ info_hash = Key(args->getByteArray("info_hash")); port = args->getInt("port"); - token = Key(args->getByteArray("token")); + token = args->getByteArray("token").left(MAX_TOKEN_SIZE); } } diff --git a/src/dht/announcetask.h b/src/dht/announcetask.h --- a/src/dht/announcetask.h +++ b/src/dht/announcetask.h @@ -30,14 +30,14 @@ class KBucketEntryAndToken : public KBucketEntry { - Key token; + QByteArray token; public: KBucketEntryAndToken() {} - KBucketEntryAndToken(const KBucketEntry & e, const Key & token) + KBucketEntryAndToken(const KBucketEntry & e, const QByteArray & token) : KBucketEntry(e), token(token) {} ~KBucketEntryAndToken() override {} - const Key & getToken() const + const QByteArray & getToken() const { return token; } diff --git a/src/dht/database.h b/src/dht/database.h --- a/src/dht/database.h +++ b/src/dht/database.h @@ -112,17 +112,17 @@ * Generate a write token, which will give peers write access to * the DB. * @param addr The address of the peer - * @return A Key + * @return A QByteArray */ - dht::Key genToken(const net::Address & addr); + QByteArray genToken(const net::Address & addr); /** * Check if a received token is OK. * @param token The token received * @param addr The address of the peer * @return true if the token was given to this peer, false other wise */ - bool checkToken(const dht::Key & token, const net::Address & addr); + bool checkToken(const QByteArray & token, const net::Address & addr); /// Test whether or not the DB contains a key bool contains(const dht::Key & key) const; @@ -132,7 +132,7 @@ private: bt::PtrMap items; - QMap tokens; + QMap tokens; }; } diff --git a/src/dht/database.cpp b/src/dht/database.cpp --- a/src/dht/database.cpp +++ b/src/dht/database.cpp @@ -127,7 +127,7 @@ } } - dht::Key Database::genToken(const net::Address & addr) + QByteArray Database::genToken(const net::Address & addr) { if (addr.ipVersion() == 4) { @@ -139,7 +139,7 @@ bt::WriteUint16(tdata, 4, addr.port()); bt::WriteUint64(tdata, 6, now); - dht::Key token = SHA1Hash::generate(tdata, 14); + QByteArray token = SHA1Hash::generate(tdata, 14).toByteArray(); // keep track of the token, tokens will expire after a while tokens.insert(token, now); return token; @@ -154,14 +154,14 @@ bt::WriteUint16(tdata, 16, addr.port()); bt::WriteUint64(tdata, 18, now); - dht::Key token = SHA1Hash::generate(tdata, 26); + QByteArray token = SHA1Hash::generate(tdata, 26).toByteArray(); // keep track of the token, tokens will expire after a while tokens.insert(token, now); return token; } } - bool Database::checkToken(const dht::Key & token, const net::Address & addr) + bool Database::checkToken(const QByteArray & token, const net::Address & addr) { // the token must be in the map if (!tokens.contains(token)) @@ -177,7 +177,7 @@ bt::WriteUint32(tdata, 0, addr.toIPv4Address()); bt::WriteUint16(tdata, 4, addr.port()); bt::WriteUint64(tdata, 6, ts); - dht::Key ct = SHA1Hash::generate(tdata, 14); + QByteArray ct = SHA1Hash::generate(tdata, 14).toByteArray(); // compare the generated token to the one received if (token != ct) // not good, this peer didn't went through the proper channels @@ -194,7 +194,7 @@ bt::WriteUint16(tdata, 16, addr.port()); bt::WriteUint64(tdata, 18, ts); - dht::Key ct = SHA1Hash::generate(tdata, 26); + QByteArray ct = SHA1Hash::generate(tdata, 26).toByteArray(); // compare the generated token to the one received if (token != ct) // not good, this peer didn't went through the proper channels { diff --git a/src/dht/dht.cpp b/src/dht/dht.cpp --- a/src/dht/dht.cpp +++ b/src/dht/dht.cpp @@ -187,7 +187,7 @@ node->received(this, r); // first check if the token is OK - dht::Key token = r.getToken(); + QByteArray token = r.getToken(); if (!db->checkToken(token, r.getOrigin())) return; @@ -215,7 +215,7 @@ db->sample(r.getInfoHash(), dbl, 50, r.getOrigin().ipVersion()); // generate a token - dht::Key token = db->genToken(r.getOrigin()); + QByteArray token = db->genToken(r.getOrigin()); bt::Uint32 wants = 0; if (r.wants(4) || r.getOrigin().ipVersion() == 4) diff --git a/src/dht/getpeersrsp.h b/src/dht/getpeersrsp.h --- a/src/dht/getpeersrsp.h +++ b/src/dht/getpeersrsp.h @@ -35,23 +35,23 @@ { public: GetPeersRsp(); - GetPeersRsp(const QByteArray & mtid, const Key & id, const Key & token); - GetPeersRsp(const QByteArray & mtid, const Key & id, const DBItemList & values, const Key & token); + GetPeersRsp(const QByteArray & mtid, const Key & id, const QByteArray & token); + GetPeersRsp(const QByteArray & mtid, const Key & id, const DBItemList & values, const QByteArray & token); ~GetPeersRsp() override; void apply(DHT* dh_table) override; void print() override; void encode(QByteArray & arr) const override; void parse(bt::BDictNode* dict) override; const DBItemList & getItemList() const {return items;} - const Key & getToken() const {return token;} + const QByteArray & getToken() const {return token;} bool containsNodes() const {return nodes.size() > 0 || nodes6.size() > 0;} bool containsValues() const {return nodes.size() == 0;} typedef QSharedPointer Ptr; private: - Key token; + QByteArray token; DBItemList items; }; diff --git a/src/dht/getpeersrsp.cpp b/src/dht/getpeersrsp.cpp --- a/src/dht/getpeersrsp.cpp +++ b/src/dht/getpeersrsp.cpp @@ -32,17 +32,17 @@ namespace dht { GetPeersRsp::GetPeersRsp() - : RPCMsg(QByteArray(), dht::GET_PEERS, dht::RSP_MSG, Key()) + : RPCMsg(QByteArray(), dht::GET_PEERS, dht::RSP_MSG, QByteArray()) { } - GetPeersRsp::GetPeersRsp(const QByteArray & mtid, const Key & id, const Key & token) + GetPeersRsp::GetPeersRsp(const QByteArray & mtid, const Key & id, const QByteArray & token) : RPCMsg(mtid, dht::GET_PEERS, dht::RSP_MSG, id), token(token) { } - GetPeersRsp::GetPeersRsp(const QByteArray & mtid, const Key & id, const DBItemList & values, const Key & token) + GetPeersRsp::GetPeersRsp(const QByteArray & mtid, const Key & id, const DBItemList & values, const QByteArray & token) : RPCMsg(mtid, dht::GET_PEERS, dht::RSP_MSG, id), token(token), items(values) @@ -82,8 +82,9 @@ enc.write(QByteArrayLiteral("nodes6")); enc.write(nodes6); } - - enc.write(QByteArrayLiteral("token")); enc.write(token.getData(), 20); + + // must cast data() to (const Uint8*) to call right write() overload + enc.write(QByteArrayLiteral("token")); enc.write((const Uint8*)token.data(), token.size()); if (items.size() > 0) { @@ -114,7 +115,7 @@ if (!args) throw bt::Error("Invalid response, arguments missing"); - token = Key(args->getByteArray("token")); + token = args->getByteArray("token").left(MAX_TOKEN_SIZE); BListNode* vals = args->getList("values"); if (vals) diff --git a/src/dht/rpcmsg.h b/src/dht/rpcmsg.h --- a/src/dht/rpcmsg.h +++ b/src/dht/rpcmsg.h @@ -34,6 +34,9 @@ namespace dht { + +#define MAX_TOKEN_SIZE 40 + class DHT; enum Type