rpc.rs
1 /* This file is part of DarkFi (https://dark.fi) 2 * 3 * Copyright (C) 2020-2025 Dyne.org foundation 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU Affero General Public License as 7 * published by the Free Software Foundation, either version 3 of the 8 * License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Affero General Public License for more details. 14 * 15 * You should have received a copy of the GNU Affero General Public License 16 * along with this program. If not, see <https://www.gnu.org/licenses/>. 17 */ 18 19 use async_trait::async_trait; 20 use darkfi::{net::P2pPtr, system::StoppableTaskPtr}; 21 use smol::lock::MutexGuard; 22 use std::collections::HashSet; 23 use tracing::debug; 24 25 use darkfi::rpc::{ 26 jsonrpc::{ErrorCode, JsonError, JsonRequest, JsonResponse, JsonResult}, 27 p2p_method::HandlerP2p, 28 server::RequestHandler, 29 util::JsonValue, 30 }; 31 32 use crate::{dchatmsg::DchatMsg, Dchat}; 33 34 #[async_trait] 35 impl RequestHandler<()> for Dchat { 36 async fn handle_request(&self, req: JsonRequest) -> JsonResult { 37 debug!(target: "dchat::rpc", "--> {}", req.stringify().unwrap()); 38 39 // ANCHOR: req_match 40 match req.method.as_str() { 41 "send" => self.send(req.id, req.params).await, 42 "recv" => self.recv(req.id).await, 43 "ping" => self.pong(req.id, req.params).await, 44 "p2p.get_info" => self.p2p_get_info(req.id, req.params).await, 45 "dnet.switch" => self.dnet_switch(req.id, req.params).await, 46 "dnet.subscribe_events" => self.dnet_subscribe_events(req.id, req.params).await, 47 _ => JsonError::new(ErrorCode::MethodNotFound, None, req.id).into(), 48 } 49 // ANCHOR_END: req_match 50 } 51 52 async fn connections_mut(&self) -> MutexGuard<'life0, HashSet<StoppableTaskPtr>> { 53 self.rpc_connections.lock().await 54 } 55 } 56 57 impl Dchat { 58 // RPCAPI: 59 // TODO 60 // --> {"jsonrpc": "2.0", "method": "send", "params": [true], "id": 42} 61 // <-- {"jsonrpc": "2.0", "result": true, "id": 42} 62 async fn send(&self, id: u16, params: JsonValue) -> JsonResult { 63 let msg = params[0].get::<String>().unwrap().to_string(); 64 let dchatmsg = DchatMsg { msg }; 65 self.p2p.broadcast(&dchatmsg).await; 66 JsonResponse::new(JsonValue::Boolean(true), id).into() 67 } 68 69 // RPCAPI: 70 // TODO 71 // --> {"jsonrpc": "2.0", "method": "inbox", "params": [true], "id": 42} 72 // <-- {"jsonrpc": "2.0", "result": true, "id": 42} 73 async fn recv(&self, id: u16) -> JsonResult { 74 let buffer = self.recv_msgs.lock().await; 75 let msgs: Vec<JsonValue> = 76 buffer.iter().map(|x| JsonValue::String(x.msg.clone())).collect(); 77 JsonResponse::new(JsonValue::Array(msgs), id).into() 78 } 79 80 // RPCAPI: 81 // Activate or deactivate dnet in the P2P stack. 82 // By sending `true`, dnet will be activated, and by sending `false` dnet will 83 // be deactivated. Returns `true` on success. 84 // 85 // --> {"jsonrpc": "2.0", "method": "dnet_switch", "params": [true], "id": 42} 86 // <-- {"jsonrpc": "2.0", "result": true, "id": 42} 87 async fn dnet_switch(&self, id: u16, params: JsonValue) -> JsonResult { 88 let params = params.get::<Vec<JsonValue>>().unwrap(); 89 if params.len() != 1 || !params[0].is_bool() { 90 return JsonError::new(ErrorCode::InvalidParams, None, id).into() 91 } 92 93 let switch = params[0].get::<bool>().unwrap(); 94 95 if *switch { 96 self.p2p.dnet_enable(); 97 } else { 98 self.p2p.dnet_disable(); 99 } 100 101 JsonResponse::new(JsonValue::Boolean(true), id).into() 102 } 103 // 104 // RPCAPI: 105 // Initializes a subscription to p2p dnet events. 106 // Once a subscription is established, `darkirc` will send JSON-RPC notifications of 107 // new network events to the subscriber. 108 // 109 // --> {"jsonrpc": "2.0", "method": "dnet.subscribe_events", "params": [], "id": 1} 110 // <-- {"jsonrpc": "2.0", "method": "dnet.subscribe_events", "params": [`event`]} 111 pub async fn dnet_subscribe_events(&self, id: u16, params: JsonValue) -> JsonResult { 112 let params = params.get::<Vec<JsonValue>>().unwrap(); 113 if !params.is_empty() { 114 return JsonError::new(ErrorCode::InvalidParams, None, id).into() 115 } 116 117 self.dnet_sub.clone().into() 118 } 119 } 120 121 impl HandlerP2p for Dchat { 122 fn p2p(&self) -> P2pPtr { 123 self.p2p.clone() 124 } 125 }