1 /* 2 SPDX-FileCopyrightText: 2012 Joris Guisson <joris.guisson@gmail.com> 3 4 SPDX-License-Identifier: GPL-2.0-or-later 5 */ 6 7 #include "rpcmsgfactory.h" 8 #include "announcereq.h" 9 #include "announcersp.h" 10 #include "dht.h" 11 #include "errmsg.h" 12 #include "findnodereq.h" 13 #include "findnodersp.h" 14 #include "getpeersrsp.h" 15 #include "pingreq.h" 16 #include "pingrsp.h" 17 #include "rpcserver.h" 18 #include <bcodec/bnode.h> 19 #include <util/error.h> 20 #include <util/functions.h> 21 #include <util/log.h> 22 23 using namespace bt; 24 25 namespace dht 26 { RPCMsgFactory()27RPCMsgFactory::RPCMsgFactory() 28 { 29 } 30 ~RPCMsgFactory()31RPCMsgFactory::~RPCMsgFactory() 32 { 33 } 34 buildRequest(BDictNode * dict)35RPCMsg::Ptr RPCMsgFactory::buildRequest(BDictNode *dict) 36 { 37 BDictNode *args = dict->getDict(ARG); 38 if (!args) 39 throw bt::Error("Invalid request, arguments missing"); 40 41 RPCMsg::Ptr msg; 42 QString str = dict->getString(REQ, nullptr); 43 if (str == "ping") { 44 msg = RPCMsg::Ptr(new PingReq()); 45 msg->parse(dict); 46 return msg; 47 } else if (str == "find_node") { 48 msg = RPCMsg::Ptr(new FindNodeReq()); 49 msg->parse(dict); 50 return msg; 51 } else if (str == "get_peers") { 52 msg = RPCMsg::Ptr(new GetPeersReq()); 53 msg->parse(dict); 54 return msg; 55 } else if (str == "announce_peer") { 56 msg = RPCMsg::Ptr(new AnnounceReq()); 57 msg->parse(dict); 58 return msg; 59 } else if (str == "vote") { 60 // Some µTorrent extension to rate torrents, just ignore 61 return msg; 62 } else 63 throw bt::Error(QString("Invalid request type %1").arg(str)); 64 } 65 buildResponse(BDictNode * dict,dht::RPCMethodResolver * method_resolver)66RPCMsg::Ptr RPCMsgFactory::buildResponse(BDictNode *dict, dht::RPCMethodResolver *method_resolver) 67 { 68 BDictNode *args = dict->getDict(RSP); 69 if (!args) 70 throw bt::Error("Arguments missing for DHT response"); 71 72 QByteArray mtid = dict->getByteArray(TID); 73 // check for empty byte arrays should prevent 144416 74 if (mtid.size() == 0) 75 throw bt::Error("Empty transaction ID in DHT response"); 76 77 RPCMsg::Ptr msg; 78 79 // find the call 80 Method method = method_resolver->findMethod(mtid); 81 switch (method) { 82 case PING: 83 msg = RPCMsg::Ptr(new PingRsp()); 84 msg->parse(dict); 85 break; 86 case FIND_NODE: 87 msg = RPCMsg::Ptr(new FindNodeRsp()); 88 msg->parse(dict); 89 break; 90 case GET_PEERS: 91 msg = RPCMsg::Ptr(new GetPeersRsp()); 92 msg->parse(dict); 93 break; 94 case ANNOUNCE_PEER: 95 msg = RPCMsg::Ptr(new AnnounceRsp()); 96 msg->parse(dict); 97 break; 98 case NONE: 99 default: 100 throw bt::Error(QString("Unknown DHT rpc call (transaction id = %1)").arg(mtid[0])); 101 } 102 103 return msg; 104 } 105 build(bt::BDictNode * dict,RPCMethodResolver * method_resolver)106RPCMsg::Ptr RPCMsgFactory::build(bt::BDictNode *dict, RPCMethodResolver *method_resolver) 107 { 108 QString t = dict->getString(TYP, nullptr); 109 if (t == REQ) { 110 return buildRequest(dict); 111 } else if (t == RSP) { 112 return buildResponse(dict, method_resolver); 113 } else if (t == ERR_DHT) { 114 RPCMsg::Ptr msg(new ErrMsg()); 115 msg->parse(dict); 116 return msg; 117 } else 118 throw bt::Error(QString("Unknown message type %1").arg(t)); 119 } 120 121 } 122