File indexing completed on 2025-01-05 04:37:10

0001 /*
0002     SPDX-FileCopyrightText: 2012 Joris Guisson <joris.guisson@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "getpeersrsp.h"
0008 #include "dht.h"
0009 #include <bcodec/bencoder.h>
0010 #include <bcodec/bnode.h>
0011 #include <util/error.h>
0012 #include <util/functions.h>
0013 #include <util/log.h>
0014 
0015 using namespace bt;
0016 
0017 namespace dht
0018 {
0019 GetPeersRsp::GetPeersRsp()
0020     : RPCMsg(QByteArray(), dht::GET_PEERS, dht::RSP_MSG, QByteArray())
0021 {
0022 }
0023 
0024 GetPeersRsp::GetPeersRsp(const QByteArray &mtid, const Key &id, const QByteArray &token)
0025     : RPCMsg(mtid, dht::GET_PEERS, dht::RSP_MSG, id)
0026     , token(token)
0027 {
0028 }
0029 
0030 GetPeersRsp::GetPeersRsp(const QByteArray &mtid, const Key &id, const DBItemList &values, const QByteArray &token)
0031     : RPCMsg(mtid, dht::GET_PEERS, dht::RSP_MSG, id)
0032     , token(token)
0033     , items(values)
0034 {
0035 }
0036 
0037 GetPeersRsp::~GetPeersRsp()
0038 {
0039 }
0040 
0041 void GetPeersRsp::apply(dht::DHT *dh_table)
0042 {
0043     dh_table->response(*this);
0044 }
0045 
0046 void GetPeersRsp::print()
0047 {
0048     Out(SYS_DHT | LOG_DEBUG) << QString("RSP: %1 %2 : get_peers(%3)").arg(mtid[0]).arg(id.toString()).arg(nodes.size() > 0 ? "nodes" : "values") << endl;
0049 }
0050 
0051 void GetPeersRsp::encode(QByteArray &arr) const
0052 {
0053     BEncoder enc(new BEncoderBufferOutput(arr));
0054     enc.beginDict();
0055     {
0056         enc.write(RSP);
0057         enc.beginDict();
0058         {
0059             enc.write(QByteArrayLiteral("id"));
0060             enc.write(id.getData(), 20);
0061             if (nodes.size() > 0) {
0062                 enc.write(QByteArrayLiteral("nodes"));
0063                 enc.write(nodes);
0064             }
0065 
0066             if (nodes6.size() > 0) {
0067                 enc.write(QByteArrayLiteral("nodes6"));
0068                 enc.write(nodes6);
0069             }
0070 
0071             // must cast data() to (const Uint8*) to call right write() overload
0072             enc.write(QByteArrayLiteral("token"));
0073             enc.write((const Uint8 *)token.data(), token.size());
0074 
0075             if (items.size() > 0) {
0076                 enc.write(QByteArrayLiteral("values"));
0077                 enc.beginList();
0078                 DBItemList::const_iterator i = items.begin();
0079                 while (i != items.end()) {
0080                     const DBItem &item = *i;
0081                     Uint8 tmp[18];
0082                     Uint32 b = item.pack(tmp);
0083                     enc.write(tmp, b);
0084                     ++i;
0085                 }
0086                 enc.end();
0087             }
0088         }
0089         enc.end();
0090         enc.write(TID);
0091         enc.write(mtid);
0092         enc.write(TYP);
0093         enc.write(RSP);
0094     }
0095     enc.end();
0096 }
0097 
0098 void GetPeersRsp::parse(BDictNode *dict)
0099 {
0100     dht::RPCMsg::parse(dict);
0101     BDictNode *args = dict->getDict(RSP);
0102     if (!args)
0103         throw bt::Error("Invalid response, arguments missing");
0104 
0105     token = args->getByteArray("token").left(MAX_TOKEN_SIZE);
0106 
0107     BListNode *vals = args->getList("values");
0108     if (vals) {
0109         for (Uint32 i = 0; i < vals->getNumChildren(); i++) {
0110             QByteArray d = vals->getByteArray(i);
0111             if (d.length() == 6) { // IPv4
0112                 Uint16 port = bt::ReadUint16((const Uint8 *)d.data(), 4);
0113                 Uint32 ip = bt::ReadUint32((const Uint8 *)d.data(), 0);
0114                 net::Address addr(QHostAddress(ip), port);
0115                 items.append(DBItem(addr));
0116             } else if (d.length() == 18) { // IPv6
0117                 Uint16 port = bt::ReadUint16((const Uint8 *)d.data(), 16);
0118                 Q_IPV6ADDR ip;
0119                 memcpy(ip.c, d.data(), 16);
0120                 net::Address addr(QHostAddress(ip), port);
0121                 items.append(DBItem(addr));
0122             }
0123         }
0124     }
0125 
0126     if (args->getValue("nodes") || args->getList("nodes6")) {
0127         BValueNode *v = args->getValue("nodes");
0128         if (v)
0129             nodes = v->data().toByteArray();
0130 
0131         v = args->getValue("nodes6");
0132         if (v)
0133             nodes6 = v->data().toByteArray();
0134     }
0135 }
0136 }