@@ -968,6 +968,54 @@ static RPCHelpMan addpeeraddress()
968968 };
969969}
970970
971+ static RPCHelpMan sendmsgtopeer ()
972+ {
973+ return RPCHelpMan{
974+ " sendmsgtopeer" ,
975+ " Send a p2p message to a peer specified by id.\n "
976+ " The message type and body must be provided, the message header will be generated.\n "
977+ " This RPC is for testing only." ,
978+ {
979+ {" peer_id" , RPCArg::Type::NUM, RPCArg::Optional::NO, " The peer to send the message to." },
980+ {" msg_type" , RPCArg::Type::STR, RPCArg::Optional::NO, strprintf (" The message type (maximum length %i)" , CMessageHeader::COMMAND_SIZE)},
981+ {" msg" , RPCArg::Type::STR_HEX, RPCArg::Optional::NO, " The serialized message body to send, in hex, without a message header" },
982+ },
983+ RPCResult{RPCResult::Type::OBJ, " " , " " , std::vector<RPCResult>{}},
984+ RPCExamples{
985+ HelpExampleCli (" sendmsgtopeer" , " 0 \" addr\" \" ffffff\" " ) + HelpExampleRpc (" sendmsgtopeer" , " 0 \" addr\" \" ffffff\" " )},
986+ [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
987+ const NodeId peer_id{request.params [0 ].getInt <int64_t >()};
988+ const std::string& msg_type{request.params [1 ].get_str ()};
989+ if (msg_type.size () > CMessageHeader::COMMAND_SIZE) {
990+ throw JSONRPCError (RPC_INVALID_PARAMETER, strprintf (" Error: msg_type too long, max length is %i" , CMessageHeader::COMMAND_SIZE));
991+ }
992+ auto msg{TryParseHex<unsigned char >(request.params [2 ].get_str ())};
993+ if (!msg.has_value ()) {
994+ throw JSONRPCError (RPC_INVALID_PARAMETER, " Error parsing input for msg" );
995+ }
996+
997+ NodeContext& node = EnsureAnyNodeContext (request.context );
998+ CConnman& connman = EnsureConnman (node);
999+
1000+ CSerializedNetMsg msg_ser;
1001+ msg_ser.data = msg.value ();
1002+ msg_ser.m_type = msg_type;
1003+
1004+ bool success = connman.ForNode (peer_id, [&](CNode* node) {
1005+ connman.PushMessage (node, std::move (msg_ser));
1006+ return true ;
1007+ });
1008+
1009+ if (!success) {
1010+ throw JSONRPCError (RPC_MISC_ERROR, " Error: Could not send message to peer" );
1011+ }
1012+
1013+ UniValue ret{UniValue::VOBJ};
1014+ return ret;
1015+ },
1016+ };
1017+ }
1018+
9711019void RegisterNetRPCCommands (CRPCTable& t)
9721020{
9731021 static const CRPCCommand commands[]{
@@ -986,6 +1034,7 @@ void RegisterNetRPCCommands(CRPCTable& t)
9861034 {" network" , &getnodeaddresses},
9871035 {" hidden" , &addconnection},
9881036 {" hidden" , &addpeeraddress},
1037+ {" hidden" , &sendmsgtopeer},
9891038 };
9901039 for (const auto & c : commands) {
9911040 t.appendCommand (c.name , &c);
0 commit comments