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 }