server.rs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2026 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. use std::{collections::HashSet, future::Future, io::ErrorKind, sync::Arc};
  19. use async_trait::async_trait;
  20. use parking_lot::Mutex as SyncMutex;
  21. use smol::{
  22. io::{BufReader, ReadHalf, WriteHalf},
  23. lock::{Mutex, MutexGuard},
  24. };
  25. use tinyjson::JsonValue;
  26. use tracing::{debug, info, warn};
  27. use url::Url;
  28. use super::{
  29. common::{
  30. http_read_from_stream_request, http_write_to_stream, read_from_stream, write_to_stream,
  31. INIT_BUF_SIZE,
  32. },
  33. jsonrpc::*,
  34. settings::RpcSettings,
  35. };
  36. use crate::{
  37. net::transport::{Listener, PtListener, PtStream},
  38. system::{StoppableTask, StoppableTaskPtr},
  39. util::logger::verbose,
  40. Error, Result,
  41. };
  42. /// Asynchronous trait implementing a handler for incoming JSON-RPC requests.
  43. #[async_trait]
  44. pub trait RequestHandler<T>: Sync + Send {
  45. async fn handle_request(&self, req: JsonRequest) -> JsonResult;
  46. async fn pong(&self, id: i64, _params: JsonValue) -> JsonResult {
  47. JsonResponse::new(JsonValue::String("pong".to_string()), id).into()
  48. }
  49. async fn connections_mut(&self) -> MutexGuard<'life0, HashSet<StoppableTaskPtr>>;
  50. async fn connections(&self) -> Vec<StoppableTaskPtr> {
  51. self.connections_mut().await.iter().cloned().collect()
  52. }
  53. async fn mark_connection(&self, task: StoppableTaskPtr) {
  54. self.connections_mut().await.insert(task);
  55. }
  56. async fn unmark_connection(&self, task: StoppableTaskPtr) {
  57. self.connections_mut().await.remove(&task);
  58. }
  59. async fn active_connections(&self) -> usize {
  60. self.connections_mut().await.len()
  61. }
  62. async fn stop_connections(&self) {
  63. info!(target: "rpc::server", "[RPC] Server stopped, closing connections");
  64. for (i, task) in self.connections().await.iter().enumerate() {
  65. debug!(target: "rpc::server", "Stopping connection #{i}");
  66. task.stop().await;
  67. }
  68. }
  69. }
  70. #[derive(Default)]
  71. struct ConnectionTaskState {
  72. closing: bool,
  73. tasks: HashSet<StoppableTaskPtr>,
  74. }
  75. #[derive(Default)]
  76. struct ConnectionTasks {
  77. state: SyncMutex<ConnectionTaskState>,
  78. }
  79. impl ConnectionTasks {
  80. /// Register and start a child while holding the task-set lock. This prevents
  81. /// a fast child from finishing before it has been registered and prevents
  82. /// new children from racing with connection shutdown.
  83. fn start<'a, MainFut>(
  84. self: &Arc<Self>,
  85. task: StoppableTaskPtr,
  86. main: MainFut,
  87. ex: Arc<smol::Executor<'a>>,
  88. ) where
  89. MainFut: Future<Output = Result<()>> + Send + 'a,
  90. {
  91. let mut state = self.state.lock();
  92. if state.closing {
  93. return
  94. }
  95. debug!(target: "rpc::server", "Adding background task {} to map", task.task_id);
  96. state.tasks.insert(task.clone());
  97. let tasks = self.clone();
  98. let task_ = task.clone();
  99. task.start(
  100. main,
  101. move |_| async move {
  102. debug!(
  103. target: "rpc::server",
  104. "Removing background task {} from map", task_.task_id,
  105. );
  106. tasks.state.lock().tasks.remove(&task_);
  107. },
  108. Error::DetachedTaskStopped,
  109. ex,
  110. );
  111. }
  112. fn close(&self) -> Vec<StoppableTaskPtr> {
  113. let mut state = self.state.lock();
  114. state.closing = true;
  115. state.tasks.iter().cloned().collect()
  116. }
  117. fn stop_all_nowait(&self) {
  118. for task in self.close() {
  119. task.stop_nowait();
  120. }
  121. }
  122. async fn stop_all(&self) {
  123. for task in self.close() {
  124. task.stop().await;
  125. }
  126. debug_assert!(self.state.lock().tasks.is_empty());
  127. }
  128. }
  129. struct ConnectionTasksGuard(Arc<ConnectionTasks>);
  130. impl Drop for ConnectionTasksGuard {
  131. fn drop(&mut self) {
  132. self.0.stop_all_nowait();
  133. }
  134. }
  135. /// Auxiliary function to handle a request in the background.
  136. async fn handle_request<T>(
  137. writer: Arc<Mutex<WriteHalf<Box<dyn PtStream>>>>,
  138. addr: Url,
  139. rh: Arc<impl RequestHandler<T> + 'static>,
  140. ex: Arc<smol::Executor<'_>>,
  141. tasks: Arc<ConnectionTasks>,
  142. settings: RpcSettings,
  143. req: JsonRequest,
  144. ) -> Result<()> {
  145. let req_id = req.id;
  146. // Handle disabled RPC methods
  147. let rep = if settings.is_method_disabled(&req.method) {
  148. debug!(target: "rpc::server", "RPC method {} is disabled", req.method);
  149. JsonError::new(ErrorCode::MethodNotFound, None, req.id).into()
  150. } else {
  151. rh.handle_request(req).await
  152. };
  153. match rep {
  154. JsonResult::Subscriber(subscriber) => {
  155. let task = StoppableTask::new();
  156. // Clone what needs to go in the background
  157. let addr_ = addr.clone();
  158. let writer_ = writer.clone();
  159. // Detach the subscriber so we can multiplex further requests
  160. tasks.start(
  161. task,
  162. async move {
  163. // Subscribe to the inner method subscriber
  164. let subscription = subscriber.publisher.subscribe().await;
  165. loop {
  166. // Listen for notifications
  167. let notification = subscription.receive().await;
  168. // Push notification
  169. debug!(target: "rpc::server", "{addr_} <-- {}", notification.stringify().unwrap());
  170. let notification = JsonResult::Notification(notification);
  171. let mut writer_lock = writer_.lock().await;
  172. #[allow(clippy::collapsible_else_if)]
  173. if settings.use_http() {
  174. if let Err(e) = http_write_to_stream(&mut writer_lock, &notification).await {
  175. return Err(e.into())
  176. }
  177. } else {
  178. if let Err(e) = write_to_stream(&mut writer_lock, &notification).await {
  179. return Err(e.into())
  180. }
  181. }
  182. drop(writer_lock);
  183. }
  184. },
  185. ex.clone(),
  186. );
  187. }
  188. JsonResult::SubscriberWithReply(subscriber, reply) => {
  189. // Write the response
  190. debug!(target: "rpc::server", "{addr} <-- {}", reply.stringify()?);
  191. let mut writer_lock = writer.lock().await;
  192. if settings.use_http() {
  193. http_write_to_stream(&mut writer_lock, &reply.into()).await?;
  194. } else {
  195. write_to_stream(&mut writer_lock, &reply.into()).await?;
  196. }
  197. drop(writer_lock);
  198. let task = StoppableTask::new();
  199. // Clone what needs to go in the background
  200. let addr_ = addr.clone();
  201. let writer_ = writer.clone();
  202. // Detach the subscriber so we can multiplex further requests
  203. tasks.start(
  204. task,
  205. async move {
  206. // Start the subscriber loop
  207. let subscription = subscriber.publisher.subscribe().await;
  208. loop {
  209. // Listen for notifications
  210. let notification = subscription.receive().await;
  211. // Push notification
  212. debug!(target: "rpc::server", "{addr_} <-- {}", notification.stringify().unwrap());
  213. let notification = JsonResult::Notification(notification);
  214. let mut writer_lock = writer_.lock().await;
  215. #[allow(clippy::collapsible_else_if)]
  216. if settings.use_http() {
  217. if let Err(e) = http_write_to_stream(&mut writer_lock, &notification).await {
  218. return Err(e.into())
  219. }
  220. } else {
  221. if let Err(e) = write_to_stream(&mut writer_lock, &notification).await {
  222. return Err(e.into())
  223. }
  224. }
  225. drop(writer_lock);
  226. }
  227. },
  228. ex.clone(),
  229. );
  230. }
  231. JsonResult::Request(_) | JsonResult::Notification(_) => {
  232. warn!(
  233. target: "rpc::server",
  234. "{addr}: handler returned Request/Notification for id={req_id}",
  235. );
  236. let err_rep: JsonResult = JsonError::new(
  237. ErrorCode::InternalError,
  238. Some("Handler returned a non-response variant".to_string()),
  239. req_id,
  240. )
  241. .into();
  242. let mut writer_lock = writer.lock().await;
  243. if settings.use_http() {
  244. http_write_to_stream(&mut writer_lock, &err_rep).await?;
  245. } else {
  246. write_to_stream(&mut writer_lock, &err_rep).await?;
  247. }
  248. drop(writer_lock);
  249. }
  250. JsonResult::Response(ref v) => {
  251. debug!(target: "rpc::server", "{addr} <-- {}", v.stringify()?);
  252. let mut writer_lock = writer.lock().await;
  253. if settings.use_http() {
  254. http_write_to_stream(&mut writer_lock, &rep).await?;
  255. } else {
  256. write_to_stream(&mut writer_lock, &rep).await?;
  257. }
  258. drop(writer_lock);
  259. }
  260. JsonResult::Error(ref v) => {
  261. debug!(target: "rpc::server", "{addr} <-- {}", v.stringify()?);
  262. let mut writer_lock = writer.lock().await;
  263. if settings.use_http() {
  264. http_write_to_stream(&mut writer_lock, &rep).await?;
  265. } else {
  266. write_to_stream(&mut writer_lock, &rep).await?;
  267. }
  268. drop(writer_lock);
  269. }
  270. }
  271. Ok(())
  272. }
  273. /// Accept function that should run inside a loop for accepting incoming
  274. /// JSON-RPC requests and passing them to the [`RequestHandler`].
  275. #[allow(clippy::type_complexity)]
  276. async fn accept_with_tasks<'a, T: 'a>(
  277. reader: Arc<Mutex<BufReader<ReadHalf<Box<dyn PtStream>>>>>,
  278. writer: Arc<Mutex<WriteHalf<Box<dyn PtStream>>>>,
  279. addr: Url,
  280. rh: Arc<impl RequestHandler<T> + 'static>,
  281. tasks: Arc<ConnectionTasks>,
  282. settings: RpcSettings,
  283. ex: Arc<smol::Executor<'a>>,
  284. ) -> Result<()> {
  285. // Ensure cancellation signals all children even before the connection
  286. // task's stop handler gets a chance to await them.
  287. let _tasks_guard = ConnectionTasksGuard(tasks.clone());
  288. loop {
  289. let mut buf = Vec::with_capacity(INIT_BUF_SIZE);
  290. let mut reader_lock = reader.lock().await;
  291. if settings.use_http() {
  292. let _ = http_read_from_stream_request(&mut reader_lock, &mut buf).await?;
  293. } else {
  294. let _ = read_from_stream(&mut reader_lock, &mut buf).await?;
  295. }
  296. drop(reader_lock);
  297. let line = match String::from_utf8(buf) {
  298. Ok(v) => v,
  299. Err(e) => {
  300. warn!(
  301. target: "rpc::server::accept",
  302. "[RPC SERVER] Failed parsing string from read buffer: {e}"
  303. );
  304. return Err(e.into())
  305. }
  306. };
  307. // Parse the line as JSON
  308. let val: JsonValue = match line.trim().parse() {
  309. Ok(v) => v,
  310. Err(e) => {
  311. warn!(
  312. target: "rpc::server::accept",
  313. "[RPC SERVER] Failed parsing JSON string: {e}"
  314. );
  315. return Err(e.into())
  316. }
  317. };
  318. // Cast to JsonRequest
  319. let req = match JsonRequest::try_from(&val) {
  320. Ok(v) => v,
  321. Err(e) => {
  322. warn!(
  323. target: "rpc::server::accept",
  324. "[RPC SERVER] Failed casting JSON to a JsonRequest: {e}"
  325. );
  326. return Err(e.into())
  327. }
  328. };
  329. debug!(target: "rpc::server", "{addr} --> {}", val.stringify()?);
  330. // Create a new task to handle request in the background
  331. let task = StoppableTask::new();
  332. // Detach the task
  333. tasks.start(
  334. task,
  335. handle_request(
  336. writer.clone(),
  337. addr.clone(),
  338. rh.clone(),
  339. ex.clone(),
  340. tasks.clone(),
  341. settings.clone(),
  342. req,
  343. ),
  344. ex.clone(),
  345. );
  346. }
  347. }
  348. /// Accept incoming JSON-RPC requests and stop all request and subscriber tasks
  349. /// before returning.
  350. #[allow(clippy::type_complexity)]
  351. pub async fn accept<'a, T: 'a>(
  352. reader: Arc<Mutex<BufReader<ReadHalf<Box<dyn PtStream>>>>>,
  353. writer: Arc<Mutex<WriteHalf<Box<dyn PtStream>>>>,
  354. addr: Url,
  355. rh: Arc<impl RequestHandler<T> + 'static>,
  356. settings: RpcSettings,
  357. ex: Arc<smol::Executor<'a>>,
  358. ) -> Result<()> {
  359. let tasks = Arc::new(ConnectionTasks::default());
  360. let result = accept_with_tasks(reader, writer, addr, rh, tasks.clone(), settings, ex).await;
  361. tasks.stop_all().await;
  362. result
  363. }
  364. /// Wrapper function around [`accept()`] to take the incoming connection and
  365. /// pass it forward.
  366. async fn run_accept_loop<'a, T: 'a>(
  367. listener: Box<dyn PtListener>,
  368. rh: Arc<impl RequestHandler<T> + 'static>,
  369. conn_limit: Option<usize>,
  370. settings: RpcSettings,
  371. ex: Arc<smol::Executor<'a>>,
  372. ) -> Result<()> {
  373. loop {
  374. let connection = match listener.next().await {
  375. Ok(negotiation) => negotiation.await,
  376. Err(err) => Err(err),
  377. };
  378. match connection {
  379. Ok((stream, url)) => {
  380. let rh_ = rh.clone();
  381. verbose!(target: "rpc::server", "[RPC] Server accepted conn from {url}");
  382. // Enforce the connection limit here, before mark_connection,
  383. // so the active count never crosses the limit.
  384. if let Some(limit) = conn_limit {
  385. if rh.active_connections().await >= limit {
  386. debug!(
  387. target: "rpc::server::run_accept_loop",
  388. "[RPC] Connection limit ({limit}) reached, rejecting {url}",
  389. );
  390. // Send a JSONRPC error before dropping the stream so
  391. // the client can tell "rejected" apart from "unreachabl;e".
  392. let err: JsonResult = JsonError::new(
  393. ErrorCode::ServerError(-32000),
  394. Some("Server connection limit reached".to_string()),
  395. 0,
  396. )
  397. .into();
  398. let (_, mut writer) = smol::io::split(stream);
  399. if settings.use_http() {
  400. let _ = http_write_to_stream(&mut writer, &err).await;
  401. } else {
  402. let _ = write_to_stream(&mut writer, &err).await;
  403. }
  404. // Writer drops here, closing the connection
  405. continue
  406. }
  407. }
  408. let (reader, writer) = smol::io::split(stream);
  409. let reader = Arc::new(Mutex::new(BufReader::new(reader)));
  410. let writer = Arc::new(Mutex::new(writer));
  411. let task = StoppableTask::new();
  412. let task_ = task.clone();
  413. let ex_ = ex.clone();
  414. let tasks = Arc::new(ConnectionTasks::default());
  415. let tasks_ = tasks.clone();
  416. // Register before starting so a connection that closes
  417. // immediately cannot finish before it is tracked.
  418. let mut connections = rh.connections_mut().await;
  419. connections.insert(task.clone());
  420. task.clone().start(
  421. accept_with_tasks(
  422. reader,
  423. writer,
  424. url.clone(),
  425. rh.clone(),
  426. tasks,
  427. settings.clone(),
  428. ex_,
  429. ),
  430. |_| async move {
  431. tasks_.stop_all().await;
  432. verbose!(target: "rpc::server", "[RPC] Closed conn from {url}");
  433. rh_.clone().unmark_connection(task_.clone()).await;
  434. },
  435. Error::ChannelStopped,
  436. ex.clone(),
  437. );
  438. drop(connections);
  439. }
  440. // As per accept(2) recommendation:
  441. Err(e) if e.raw_os_error().is_some() => match e.raw_os_error().unwrap() {
  442. libc::EAGAIN | libc::ECONNABORTED | libc::EPROTO | libc::EINTR => continue,
  443. libc::ECONNRESET => {
  444. warn!(
  445. target: "rpc::server::run_accept_loop",
  446. "[RPC] Connection reset by peer in accept_loop"
  447. );
  448. continue
  449. }
  450. libc::ETIMEDOUT => {
  451. warn!(
  452. target: "rpc::server::run_accept_loop",
  453. "[RPC] Connection timed out in accept_loop"
  454. );
  455. continue
  456. }
  457. libc::EPIPE => {
  458. warn!(
  459. target: "rpc::server::run_accept_loop",
  460. "[RPC] Broken pipe in accept_loop"
  461. );
  462. continue
  463. }
  464. x => {
  465. warn!(
  466. target: "rpc::server::run_accept_loop",
  467. "[RPC] Unhandled OS Error: {e} {x}"
  468. );
  469. continue
  470. }
  471. },
  472. // In case a TLS handshake fails, we'll get this:
  473. Err(e) if e.kind() == ErrorKind::UnexpectedEof => continue,
  474. // Handle ErrorKind::Other
  475. Err(e) if e.kind() == ErrorKind::Other => {
  476. if let Some(inner) = std::error::Error::source(&e) {
  477. if let Some(inner) = inner.downcast_ref::<futures_rustls::rustls::Error>() {
  478. warn!(
  479. target: "rpc::server::run_accept_loop",
  480. "[RPC] rustls listener error: {inner:?}"
  481. );
  482. continue
  483. }
  484. }
  485. warn!(
  486. target: "rpc::server::run_accept_loop",
  487. "[RPC] Unhandled ErrorKind::Other error: {e:?}"
  488. );
  489. continue
  490. }
  491. // Errors we didn't handle above:
  492. Err(e) => {
  493. warn!(
  494. target: "rpc::server::run_accept_loop",
  495. "[RPC] Unhandled listener.next() error: {e}"
  496. );
  497. continue
  498. }
  499. }
  500. }
  501. }
  502. /// Start a JSON-RPC server bound to the givven accept URL and use the
  503. /// given [`RequestHandler`] to handle incoming requests.
  504. ///
  505. /// The supported network schemes can be prefixed with `http+` to serve
  506. /// JSON-RPC over HTTP/1.1.
  507. pub async fn listen_and_serve<'a, T: 'a>(
  508. settings: RpcSettings,
  509. rh: Arc<impl RequestHandler<T> + 'static>,
  510. conn_limit: Option<usize>,
  511. ex: Arc<smol::Executor<'a>>,
  512. ) -> Result<()> {
  513. // Figure out if we're using HTTP and rewrite the URL accordingly.
  514. let mut listen_url = settings.listen.clone();
  515. if settings.listen.scheme().starts_with("http+") {
  516. let scheme = settings.listen.scheme().strip_prefix("http+").unwrap();
  517. let url_str = settings.listen.as_str().replace(settings.listen.scheme(), scheme);
  518. listen_url = url_str.parse()?;
  519. }
  520. let listener = Listener::new(listen_url, None, false).await?.listen().await?;
  521. run_accept_loop(listener, rh, conn_limit, settings, ex.clone()).await
  522. }
  523. #[cfg(test)]
  524. mod tests {
  525. use super::*;
  526. use crate::{
  527. rpc::client::RpcClient,
  528. system::{msleep, Publisher},
  529. };
  530. use smol::{net::TcpListener, Executor};
  531. struct RpcServer {
  532. rpc_connections: Mutex<HashSet<StoppableTaskPtr>>,
  533. subscriber: JsonSubscriber,
  534. }
  535. #[async_trait]
  536. impl RequestHandler<()> for RpcServer {
  537. async fn handle_request(&self, req: JsonRequest) -> JsonResult {
  538. match req.method.as_str() {
  539. "ping" => return self.pong(req.id, req.params).await,
  540. "subscribe" => return self.subscriber.clone().into(),
  541. _ => panic!(),
  542. }
  543. }
  544. async fn connections_mut(&self) -> MutexGuard<'life0, HashSet<StoppableTaskPtr>> {
  545. self.rpc_connections.lock().await
  546. }
  547. }
  548. #[test]
  549. fn conn_manager() -> Result<()> {
  550. let executor = Arc::new(Executor::new());
  551. // This simulates a server and a client. Through the function, there
  552. // are some calls to sleep(), which are used for the tests, because
  553. // otherwise they execute too fast. In practice, The RPC server is
  554. // a long-running task so when polled, it should handle things in a
  555. // correct manner.
  556. smol::block_on(executor.run(async {
  557. // Find an available port
  558. let listener = TcpListener::bind("127.0.0.1:0").await?;
  559. let sockaddr = listener.local_addr()?;
  560. let settings = RpcSettings {
  561. listen: Url::parse(&format!("tcp://127.0.0.1:{}", sockaddr.port()))?,
  562. disabled_methods: vec![],
  563. };
  564. drop(listener);
  565. let rpc_server = Arc::new(RpcServer {
  566. rpc_connections: Mutex::new(HashSet::new()),
  567. subscriber: JsonSubscriber::new("event"),
  568. });
  569. let rpc_server_ = rpc_server.clone();
  570. let server_task = StoppableTask::new();
  571. server_task.clone().start(
  572. listen_and_serve(settings.clone(), rpc_server.clone(), None, executor.clone()),
  573. |res| async move {
  574. match res {
  575. Ok(()) | Err(Error::RpcServerStopped) => {
  576. rpc_server_.stop_connections().await
  577. }
  578. Err(e) => panic!("{e}"),
  579. }
  580. },
  581. Error::RpcServerStopped,
  582. executor.clone(),
  583. );
  584. // Let the server spawn
  585. msleep(500).await;
  586. // Connect a client
  587. let rpc_client0 = RpcClient::new(settings.listen.clone(), executor.clone()).await?;
  588. msleep(500).await;
  589. assert!(rpc_server.active_connections().await == 1);
  590. // Connect another client
  591. let rpc_client1 = RpcClient::new(settings.listen.clone(), executor.clone()).await?;
  592. msleep(500).await;
  593. assert!(rpc_server.active_connections().await == 2);
  594. // And another one
  595. let _rpc_client2 = RpcClient::new(settings.listen.clone(), executor.clone()).await?;
  596. msleep(500).await;
  597. assert!(rpc_server.active_connections().await == 3);
  598. // Close the first client
  599. rpc_client0.stop().await;
  600. msleep(500).await;
  601. assert!(rpc_server.active_connections().await == 2);
  602. // Close the second client
  603. rpc_client1.stop().await;
  604. msleep(500).await;
  605. assert!(rpc_server.active_connections().await == 1);
  606. // The Listener should be stopped when we stop the server task.
  607. server_task.stop().await;
  608. assert!(RpcClient::new(settings.listen, executor.clone()).await.is_err());
  609. // After the server is stopped, the connections tasks should also be stopped
  610. assert!(rpc_server.active_connections().await == 0);
  611. Ok(())
  612. }))
  613. }
  614. #[test]
  615. fn subscriber_tasks_follow_connection_lifetime() -> Result<()> {
  616. let executor = Arc::new(Executor::new());
  617. smol::block_on(executor.run(async {
  618. let listener = TcpListener::bind("127.0.0.1:0").await?;
  619. let sockaddr = listener.local_addr()?;
  620. let settings = RpcSettings {
  621. listen: Url::parse(&format!("tcp://127.0.0.1:{}", sockaddr.port()))?,
  622. disabled_methods: vec![],
  623. };
  624. drop(listener);
  625. let rpc_server = Arc::new(RpcServer {
  626. rpc_connections: Mutex::new(HashSet::new()),
  627. subscriber: JsonSubscriber::new("event"),
  628. });
  629. let rpc_server_ = rpc_server.clone();
  630. let server_task = StoppableTask::new();
  631. server_task.clone().start(
  632. listen_and_serve(settings.clone(), rpc_server.clone(), None, executor.clone()),
  633. |res| async move {
  634. match res {
  635. Ok(()) | Err(Error::RpcServerStopped) => {
  636. rpc_server_.stop_connections().await
  637. }
  638. Err(e) => panic!("{e}"),
  639. }
  640. },
  641. Error::RpcServerStopped,
  642. executor.clone(),
  643. );
  644. msleep(500).await;
  645. for _ in 0..32 {
  646. let client =
  647. Arc::new(RpcClient::new(settings.listen.clone(), executor.clone()).await?);
  648. let client_ = client.clone();
  649. let subscriber_task = executor.spawn(async move {
  650. client_
  651. .subscribe(
  652. JsonRequest::new("subscribe", JsonValue::Array(vec![])),
  653. Publisher::new(),
  654. )
  655. .await
  656. });
  657. for _ in 0..100 {
  658. if rpc_server.subscriber.publisher.active_subscriptions() == 1 {
  659. break
  660. }
  661. msleep(10).await;
  662. }
  663. assert_eq!(rpc_server.subscriber.publisher.active_subscriptions(), 1);
  664. client.stop().await;
  665. assert!(subscriber_task.await.is_err());
  666. for _ in 0..100 {
  667. if rpc_server.active_connections().await == 0 {
  668. break
  669. }
  670. msleep(10).await;
  671. }
  672. assert_eq!(rpc_server.active_connections().await, 0);
  673. assert_eq!(rpc_server.subscriber.publisher.active_subscriptions(), 0);
  674. }
  675. server_task.stop().await;
  676. assert_eq!(rpc_server.active_connections().await, 0);
  677. assert_eq!(rpc_server.subscriber.publisher.active_subscriptions(), 0);
  678. Ok(())
  679. }))
  680. }
  681. }