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

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 "rpcmsgfactory.h"
0008 #include "announcereq.h"
0009 #include "announcersp.h"
0010 #include "dht.h"
0011 #include "errmsg.h"
0012 #include "findnodereq.h"
0013 #include "findnodersp.h"
0014 #include "getpeersrsp.h"
0015 #include "pingreq.h"
0016 #include "pingrsp.h"
0017 #include "rpcserver.h"
0018 #include <bcodec/bnode.h>
0019 #include <util/error.h>
0020 #include <util/functions.h>
0021 #include <util/log.h>
0022 
0023 using namespace bt;
0024 
0025 namespace dht
0026 {
0027 RPCMsgFactory::RPCMsgFactory()
0028 {
0029 }
0030 
0031 RPCMsgFactory::~RPCMsgFactory()
0032 {
0033 }
0034 
0035 RPCMsg::Ptr RPCMsgFactory::buildRequest(BDictNode *dict)
0036 {
0037     BDictNode *args = dict->getDict(ARG);
0038     if (!args)
0039         throw bt::Error("Invalid request, arguments missing");
0040 
0041     RPCMsg::Ptr msg;
0042     QString str = dict->getString(REQ, nullptr);
0043     if (str == "ping") {
0044         msg = RPCMsg::Ptr(new PingReq());
0045         msg->parse(dict);
0046         return msg;
0047     } else if (str == "find_node") {
0048         msg = RPCMsg::Ptr(new FindNodeReq());
0049         msg->parse(dict);
0050         return msg;
0051     } else if (str == "get_peers") {
0052         msg = RPCMsg::Ptr(new GetPeersReq());
0053         msg->parse(dict);
0054         return msg;
0055     } else if (str == "announce_peer") {
0056         msg = RPCMsg::Ptr(new AnnounceReq());
0057         msg->parse(dict);
0058         return msg;
0059     } else if (str == "vote") {
0060         // Some µTorrent extension to rate torrents, just ignore
0061         return msg;
0062     } else
0063         throw bt::Error(QString("Invalid request type %1").arg(str));
0064 }
0065 
0066 RPCMsg::Ptr RPCMsgFactory::buildResponse(BDictNode *dict, dht::RPCMethodResolver *method_resolver)
0067 {
0068     BDictNode *args = dict->getDict(RSP);
0069     if (!args)
0070         throw bt::Error("Arguments missing for DHT response");
0071 
0072     QByteArray mtid = dict->getByteArray(TID);
0073     // check for empty byte arrays should prevent 144416
0074     if (mtid.size() == 0)
0075         throw bt::Error("Empty transaction ID in DHT response");
0076 
0077     RPCMsg::Ptr msg;
0078 
0079     // find the call
0080     Method method = method_resolver->findMethod(mtid);
0081     switch (method) {
0082     case PING:
0083         msg = RPCMsg::Ptr(new PingRsp());
0084         msg->parse(dict);
0085         break;
0086     case FIND_NODE:
0087         msg = RPCMsg::Ptr(new FindNodeRsp());
0088         msg->parse(dict);
0089         break;
0090     case GET_PEERS:
0091         msg = RPCMsg::Ptr(new GetPeersRsp());
0092         msg->parse(dict);
0093         break;
0094     case ANNOUNCE_PEER:
0095         msg = RPCMsg::Ptr(new AnnounceRsp());
0096         msg->parse(dict);
0097         break;
0098     case NONE:
0099     default:
0100         throw bt::Error(QString("Unknown DHT rpc call (transaction id = %1)").arg(mtid[0]));
0101     }
0102 
0103     return msg;
0104 }
0105 
0106 RPCMsg::Ptr RPCMsgFactory::build(bt::BDictNode *dict, RPCMethodResolver *method_resolver)
0107 {
0108     QString t = dict->getString(TYP, nullptr);
0109     if (t == REQ) {
0110         return buildRequest(dict);
0111     } else if (t == RSP) {
0112         return buildResponse(dict, method_resolver);
0113     } else if (t == ERR_DHT) {
0114         RPCMsg::Ptr msg(new ErrMsg());
0115         msg->parse(dict);
0116         return msg;
0117     } else
0118         throw bt::Error(QString("Unknown message type %1").arg(t));
0119 }
0120 
0121 }