1use std::{
28 borrow::Cow, fmt, future::Future, net::SocketAddr, pin::Pin, sync::Arc, task::Poll,
29 time::Duration,
30};
31
32use crate::{
33 future::{ConnectionGuard, ServerHandle, StopHandle},
34 middleware::rpc::{catch_call_panic, RpcService},
35 transport::{http, ws, ws::BackgroundTaskParams},
36 utils::{
37 accept_error_backoff, deserialize_notification, no_request_within, NotifyOnRequest,
38 PermitBody, WriteTimeoutIo, DEFAULT_FIRST_REQUEST_TIMEOUT, DEFAULT_WRITE_TIMEOUT,
39 },
40 HttpBody, HttpRequest, HttpResponse, LOG_TARGET,
41};
42
43use futures_util::{
44 future::{Either, FutureExt},
45 io::{BufReader, BufWriter},
46};
47use hyper::body::{Bytes, Incoming};
48use hyper_util::{
49 rt::{TokioExecutor, TokioIo},
50 service::TowerToHyperService,
51};
52use jsonrpsee_core::{
53 id_providers::RandomIntegerIdProvider,
54 middleware::{Batch, BatchEntry, BatchEntryErr, RpcServiceBuilder, RpcServiceT},
55 server::{
56 helpers::prepare_error, BoundedSubscriptions, ConnectionId, MethodResponse, MethodSink,
57 Methods,
58 },
59 traits::IdProvider,
60 BoxError, JsonRawValue, TEN_MB_SIZE_BYTES,
61};
62use jsonrpsee_types::{
63 error::{
64 reject_too_big_batch_request, ErrorCode, BATCHES_NOT_SUPPORTED_CODE,
65 BATCHES_NOT_SUPPORTED_MSG,
66 },
67 ErrorObject, Id, Notification, Request, TwoPointZero,
68};
69use serde::{
70 de::{
71 value::MapAccessDeserializer, DeserializeSeed, Deserializer, Error as _, IgnoredAny,
72 MapAccess, SeqAccess, Visitor,
73 },
74 Deserialize,
75};
76use soketto::handshake::http::is_upgrade_request;
77use tokio::{
78 net::{TcpListener, TcpStream, ToSocketAddrs},
79 sync::{mpsc, watch, Notify, OwnedSemaphorePermit},
80};
81use tokio_util::compat::TokioAsyncReadCompatExt;
82use tower::{layer::util::Identity, Layer, Service, ServiceExt};
83use tracing::{instrument, Instrument};
84
85const MAX_CONNECTIONS: u32 = 100;
87
88pub struct Server<HttpMiddleware = Identity, RpcMiddleware = Identity> {
90 listener: TcpListener,
91 server_cfg: ServerConfig,
92 rpc_middleware: RpcServiceBuilder<RpcMiddleware>,
93 http_middleware: tower::ServiceBuilder<HttpMiddleware>,
94}
95
96impl Server<Identity, Identity> {
97 pub fn builder() -> Builder<Identity, Identity> {
99 Builder::new()
100 }
101}
102
103impl<RpcMiddleware, HttpMiddleware> std::fmt::Debug for Server<RpcMiddleware, HttpMiddleware> {
104 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105 f.debug_struct("Server")
106 .field("listener", &self.listener)
107 .field("server_cfg", &self.server_cfg)
108 .finish()
109 }
110}
111
112impl<RpcMiddleware, HttpMiddleware> Server<RpcMiddleware, HttpMiddleware> {
113 pub fn local_addr(&self) -> std::io::Result<SocketAddr> {
115 self.listener.local_addr()
116 }
117}
118
119impl<HttpMiddleware, RpcMiddleware, Body> Server<HttpMiddleware, RpcMiddleware>
120where
121 RpcMiddleware: Layer<RpcService> + Clone + Send + 'static,
122 <RpcMiddleware as Layer<RpcService>>::Service: RpcServiceT,
123 HttpMiddleware: Layer<TowerServiceNoHttp<RpcMiddleware>> + Send + 'static,
124 <HttpMiddleware as Layer<TowerServiceNoHttp<RpcMiddleware>>>::Service:
125 Service<HttpRequest, Response = HttpResponse<Body>, Error = BoxError> + Clone + Send,
126 <<HttpMiddleware as Layer<TowerServiceNoHttp<RpcMiddleware>>>::Service as Service<
127 HttpRequest,
128 >>::Future: Send,
129 Body: http_body::Body<Data = Bytes> + Send + 'static,
130 <Body as http_body::Body>::Error: Into<BoxError>,
131{
132 pub fn start(mut self, methods: impl Into<Methods>) -> ServerHandle {
137 let methods = methods.into();
138 let (stop_tx, stop_rx) = watch::channel(());
139
140 let stop_handle = StopHandle::new(stop_rx);
141
142 match self.server_cfg.tokio_runtime.take() {
143 Some(rt) => rt.spawn(self.start_inner(methods, stop_handle)),
144 None => tokio::spawn(self.start_inner(methods, stop_handle)),
145 };
146
147 ServerHandle::new(stop_tx)
148 }
149
150 async fn start_inner(self, methods: Methods, stop_handle: StopHandle) {
151 let connection_guard = ConnectionGuard::new(self.server_cfg.max_connections as usize);
152 let listener = self.listener;
153
154 let stopped = stop_handle.clone().shutdown();
155 tokio::pin!(stopped);
156
157 let (drop_on_completion, mut process_connection_awaiter) = mpsc::channel::<()>(1);
158
159 loop {
160 match try_accept_conn(&listener, stopped).await {
161 AcceptConnection::Established { socket, remote_addr, stop } => {
162 process_connection(ProcessConnection {
163 http_middleware: &self.http_middleware,
164 rpc_middleware: self.rpc_middleware.clone(),
165 remote_addr,
166 methods: methods.clone(),
167 stop_handle: stop_handle.clone(),
168 conn_id: ConnectionId::next_unique().0,
169 server_cfg: self.server_cfg.clone(),
170 conn_guard: &connection_guard,
171 socket,
172 drop_on_completion: drop_on_completion.clone(),
173 });
174 stopped = stop;
175 }
176 AcceptConnection::Err((e, stop)) => {
177 tracing::debug!(target: LOG_TARGET, "Error while awaiting a new connection: {:?}", e);
178 let Some(stop) = accept_error_backoff(&e, stop).await else { break };
179 stopped = stop;
180 }
181 AcceptConnection::Shutdown => break,
182 }
183 }
184
185 drop(drop_on_completion);
187
188 while process_connection_awaiter.recv().await.is_some() {
191 }
194 }
195}
196
197#[derive(Debug, Clone)]
199pub struct ServerConfig {
200 pub(crate) max_request_body_size: u32,
202 pub(crate) max_response_body_size: u32,
204 pub(crate) max_connections: u32,
206 pub(crate) max_subscriptions_per_connection: u32,
208 pub(crate) batch_requests_config: BatchRequestConfig,
210 pub(crate) tokio_runtime: Option<tokio::runtime::Handle>,
212 pub(crate) enable_http: bool,
214 pub(crate) enable_ws: bool,
216 pub(crate) message_buffer_capacity: u32,
218 pub(crate) id_provider: Arc<dyn IdProvider>,
220 pub(crate) first_request_timeout: Option<Duration>,
222 pub(crate) write_timeout: Duration,
225}
226
227#[derive(Debug, Clone)]
229pub struct ServerConfigBuilder(ServerConfig);
230
231#[derive(Debug, Copy, Clone)]
233pub enum BatchRequestConfig {
234 Disabled,
236 Limit(u32),
239 Unlimited,
241}
242
243#[derive(Debug, Clone)]
246pub struct ConnectionState {
247 pub(crate) stop_handle: StopHandle,
249 pub(crate) conn_id: usize,
251 pub(crate) _conn_permit: Arc<OwnedSemaphorePermit>,
253}
254
255impl ConnectionState {
256 pub fn new(
258 stop_handle: StopHandle,
259 conn_id: usize,
260 conn_permit: OwnedSemaphorePermit,
261 ) -> ConnectionState {
262 Self { stop_handle, conn_id, _conn_permit: Arc::new(conn_permit) }
263 }
264}
265
266impl Default for ServerConfig {
267 fn default() -> Self {
268 ServerConfig::builder().build()
269 }
270}
271
272impl ServerConfig {
273 pub fn builder() -> ServerConfigBuilder {
275 ServerConfigBuilder::default()
276 }
277}
278
279impl Default for ServerConfigBuilder {
280 fn default() -> Self {
281 Self(ServerConfig {
282 max_request_body_size: TEN_MB_SIZE_BYTES,
283 max_response_body_size: TEN_MB_SIZE_BYTES,
284 max_connections: MAX_CONNECTIONS,
285 max_subscriptions_per_connection: 1024,
286 batch_requests_config: BatchRequestConfig::Unlimited,
287 tokio_runtime: None,
288 enable_http: true,
289 enable_ws: true,
290 message_buffer_capacity: 1024,
291 id_provider: Arc::new(RandomIntegerIdProvider),
292 first_request_timeout: Some(DEFAULT_FIRST_REQUEST_TIMEOUT),
293 write_timeout: DEFAULT_WRITE_TIMEOUT,
294 })
295 }
296}
297
298impl ServerConfigBuilder {
299 pub fn new() -> Self {
301 Self::default()
302 }
303
304 pub fn max_request_body_size(mut self, size: u32) -> Self {
306 self.0.max_request_body_size = size;
307 self
308 }
309
310 pub fn max_response_body_size(mut self, size: u32) -> Self {
312 self.0.max_response_body_size = size;
313 self
314 }
315
316 pub fn max_connections(mut self, max: u32) -> Self {
318 self.0.max_connections = max;
319 self
320 }
321
322 pub fn max_subscriptions_per_connection(mut self, max: u32) -> Self {
324 self.0.max_subscriptions_per_connection = max;
325 self
326 }
327
328 pub fn set_batch_request_config(mut self, cfg: BatchRequestConfig) -> Self {
334 self.0.batch_requests_config = cfg;
335 self
336 }
337
338 pub fn custom_tokio_runtime(mut self, rt: tokio::runtime::Handle) -> Self {
342 self.0.tokio_runtime = Some(rt);
343 self
344 }
345
346 pub fn http_only(mut self) -> Self {
350 self.0.enable_http = true;
351 self.0.enable_ws = false;
352 self
353 }
354
355 pub fn ws_only(mut self) -> Self {
361 self.0.enable_http = false;
362 self.0.enable_ws = true;
363 self
364 }
365
366 pub fn set_message_buffer_capacity(mut self, c: u32) -> Self {
388 assert!(c > 0, "buffer capacity must be set to > 0");
389 self.0.message_buffer_capacity = c;
390 self
391 }
392
393 pub fn set_id_provider<I: IdProvider + 'static>(mut self, id_provider: I) -> Self {
414 self.0.id_provider = Arc::new(id_provider);
415 self
416 }
417
418 pub fn set_first_request_timeout(mut self, first_request_timeout: Option<Duration>) -> Self {
423 self.0.first_request_timeout = first_request_timeout;
424 self
425 }
426
427 pub fn set_write_timeout(mut self, write_timeout: Duration) -> Self {
437 self.0.write_timeout = write_timeout;
438 self
439 }
440
441 pub fn build(self) -> ServerConfig {
443 self.0
444 }
445}
446
447#[derive(Debug)]
449pub struct Builder<HttpMiddleware, RpcMiddleware> {
450 server_cfg: ServerConfig,
451 rpc_middleware: RpcServiceBuilder<RpcMiddleware>,
452 http_middleware: tower::ServiceBuilder<HttpMiddleware>,
453}
454
455impl Default for Builder<Identity, Identity> {
456 fn default() -> Self {
457 Builder {
458 server_cfg: ServerConfig::default(),
459 rpc_middleware: RpcServiceBuilder::new(),
460 http_middleware: tower::ServiceBuilder::new(),
461 }
462 }
463}
464
465impl Builder<Identity, Identity> {
466 pub fn new() -> Self {
468 Self::default()
469 }
470
471 pub fn with_config(config: ServerConfig) -> Self {
473 Self { server_cfg: config, ..Default::default() }
474 }
475}
476
477impl<HttpMiddleware, RpcMiddleware> Builder<HttpMiddleware, RpcMiddleware> {
478 pub fn set_config(mut self, cfg: ServerConfig) -> Self {
480 self.server_cfg = cfg;
481 self
482 }
483
484 pub fn set_rpc_middleware<T>(
563 self,
564 rpc_middleware: RpcServiceBuilder<T>,
565 ) -> Builder<HttpMiddleware, T> {
566 Builder {
567 server_cfg: self.server_cfg,
568 rpc_middleware,
569 http_middleware: self.http_middleware,
570 }
571 }
572
573 pub fn set_http_middleware<T>(
595 self,
596 http_middleware: tower::ServiceBuilder<T>,
597 ) -> Builder<T, RpcMiddleware> {
598 Builder {
599 server_cfg: self.server_cfg,
600 http_middleware,
601 rpc_middleware: self.rpc_middleware,
602 }
603 }
604
605 pub async fn build(
618 self,
619 addrs: impl ToSocketAddrs,
620 ) -> std::io::Result<Server<HttpMiddleware, RpcMiddleware>> {
621 let listener = TcpListener::bind(addrs).await?;
622
623 Ok(Server {
624 listener,
625 server_cfg: self.server_cfg,
626 rpc_middleware: self.rpc_middleware,
627 http_middleware: self.http_middleware,
628 })
629 }
630}
631
632#[derive(Debug, Clone)]
634struct ServiceData {
635 methods: Methods,
637 stop_handle: StopHandle,
639 conn_id: usize,
641 conn_guard: ConnectionGuard,
643 server_cfg: ServerConfig,
645}
646
647#[derive(Debug, Clone)]
652pub struct TowerServiceNoHttp<L> {
653 inner: ServiceData,
654 rpc_middleware: RpcServiceBuilder<L>,
655}
656
657impl<Body, RpcMiddleware> Service<HttpRequest<Body>> for TowerServiceNoHttp<RpcMiddleware>
658where
659 RpcMiddleware: Layer<RpcService>,
660 <RpcMiddleware as Layer<RpcService>>::Service: RpcServiceT + Send + Sync + 'static,
661 Body: http_body::Body<Data = Bytes> + Send + 'static,
662 <Body as http_body::Body>::Error: Into<BoxError>,
663{
664 type Response = HttpResponse;
665
666 type Error = BoxError;
670
671 type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
672
673 fn poll_ready(&mut self, _cx: &mut std::task::Context<'_>) -> Poll<Result<(), Self::Error>> {
674 Poll::Ready(Ok(()))
675 }
676
677 fn call(&mut self, request: HttpRequest<Body>) -> Self::Future {
678 let request = request.map(HttpBody::new);
679
680 let conn_guard = &self.inner.conn_guard;
681 let stop_handle = self.inner.stop_handle.clone();
682 let conn_id = self.inner.conn_id;
683
684 tracing::trace!(target: LOG_TARGET, "{:?}", request);
685
686 let Some(conn_permit) = conn_guard.try_acquire() else {
687 return async move { Ok(http::response::too_many_requests()) }.boxed();
688 };
689
690 let conn = ConnectionState::new(stop_handle.clone(), conn_id, conn_permit);
691
692 let max_conns = conn_guard.max_connections();
693 let curr_conns = max_conns - conn_guard.available_connections();
694 tracing::debug!(target: LOG_TARGET, "Accepting new connection {}/{}", curr_conns, max_conns);
695
696 let is_upgrade_request = is_upgrade_request(&request);
697
698 if self.inner.server_cfg.enable_ws && is_upgrade_request {
699 let this = self.inner.clone();
700
701 let mut server = soketto::handshake::http::Server::new();
702
703 let response = match server.receive_request(&request) {
704 Ok(response) => {
705 let (tx, rx) = mpsc::channel(this.server_cfg.message_buffer_capacity as usize);
706 let sink =
707 MethodSink::new_with_limit(tx, this.server_cfg.max_response_body_size);
708
709 let (pending_calls, pending_calls_completed) = mpsc::channel::<()>(1);
713
714 let rpc_service = RpcService::new(
715 this.methods.clone(),
716 this.server_cfg.max_response_body_size as usize,
717 this.conn_id.into(),
718 BoundedSubscriptions::new(this.server_cfg.max_subscriptions_per_connection),
719 sink.clone(),
720 this.server_cfg.id_provider.clone(),
721 );
722
723 let rpc_service = self.rpc_middleware.service(rpc_service);
724
725 tokio::spawn(
726 async move {
727 let upgraded = match hyper::upgrade::on(request).await {
728 Ok(u) => u,
729 Err(e) => {
730 tracing::debug!(target: LOG_TARGET, "Could not upgrade connection: {}", e);
731 return;
732 }
733 };
734
735 let io = TokioIo::new(upgraded);
736
737 let stream = BufReader::new(BufWriter::new(io.compat()));
738 let mut ws_builder = server.into_builder(stream);
739 ws_builder.set_max_message_size(this.server_cfg.max_request_body_size as usize);
740 let (sender, receiver) = ws_builder.finish();
741
742 let params = BackgroundTaskParams {
743 server_cfg: this.server_cfg,
744 conn,
745 ws_sender: sender,
746 ws_receiver: receiver,
747 rpc_service,
748 sink,
749 rx,
750 pending_calls,
751 pending_calls_completed,
752 };
753
754 ws::background_task(params).await;
755 }
756 .in_current_span(),
757 );
758
759 response.map(|()| HttpBody::empty())
760 }
761 Err(e) => {
762 tracing::debug!(target: LOG_TARGET, "Could not upgrade connection: {}", e);
763 HttpResponse::new(HttpBody::from(format!("Could not upgrade connection: {e}")))
764 }
765 };
766
767 async { Ok(response) }.boxed()
768 } else if self.inner.server_cfg.enable_http && !is_upgrade_request {
769 let this = &self.inner;
770 let max_response_size = this.server_cfg.max_response_body_size;
771 let max_request_size = this.server_cfg.max_request_body_size;
772 let methods = this.methods.clone();
773 let batch_config = this.server_cfg.batch_requests_config;
774
775 let rpc_service = self.rpc_middleware.service(RpcService::without_subscriptions(
776 methods,
777 max_response_size as usize,
778 this.conn_id.into(),
779 ));
780
781 Box::pin(async move {
782 let rp =
783 http::call_with_service(request, batch_config, max_request_size, rpc_service)
784 .await;
785 Ok(rp.map(|body| HttpBody::new(PermitBody::new(body, conn))))
789 })
790 } else {
791 Box::pin(async { Ok(http::response::denied()) })
794 }
795 }
796}
797
798struct ProcessConnection<'a, HttpMiddleware, RpcMiddleware> {
799 http_middleware: &'a tower::ServiceBuilder<HttpMiddleware>,
800 rpc_middleware: RpcServiceBuilder<RpcMiddleware>,
801 conn_guard: &'a ConnectionGuard,
802 conn_id: usize,
803 server_cfg: ServerConfig,
804 stop_handle: StopHandle,
805 socket: TcpStream,
806 drop_on_completion: mpsc::Sender<()>,
807 remote_addr: SocketAddr,
808 methods: Methods,
809}
810
811#[instrument(name = "connection", target = LOG_TARGET, skip_all, fields(remote_addr = %params.remote_addr, conn_id = %params.conn_id), level = "INFO")]
812fn process_connection<RpcMiddleware, HttpMiddleware, Body>(
813 params: ProcessConnection<HttpMiddleware, RpcMiddleware>,
814) where
815 HttpMiddleware: Layer<TowerServiceNoHttp<RpcMiddleware>> + Send + 'static,
816 <HttpMiddleware as Layer<TowerServiceNoHttp<RpcMiddleware>>>::Service: Service<HttpRequest, Response = HttpResponse<Body>, Error = BoxError>
817 + Clone
818 + Send
819 + 'static,
820 <<HttpMiddleware as Layer<TowerServiceNoHttp<RpcMiddleware>>>::Service as Service<
821 HttpRequest,
822 >>::Future: Send + 'static,
823 Body: http_body::Body<Data = Bytes> + Send + 'static,
824 <Body as http_body::Body>::Error: Into<BoxError>,
825{
826 let ProcessConnection {
827 http_middleware,
828 rpc_middleware,
829 conn_guard,
830 conn_id,
831 server_cfg,
832 socket,
833 stop_handle,
834 drop_on_completion,
835 methods,
836 ..
837 } = params;
838
839 if let Err(e) = socket.set_nodelay(true) {
840 tracing::warn!(target: LOG_TARGET, "Could not set NODELAY on socket: {:?}", e);
841 return;
842 }
843
844 let first_request_timeout = server_cfg.first_request_timeout;
845 let write_timeout = server_cfg.write_timeout;
846
847 let tower_service = TowerServiceNoHttp {
848 inner: ServiceData {
849 server_cfg,
850 methods,
851 stop_handle: stop_handle.clone(),
852 conn_id,
853 conn_guard: conn_guard.clone(),
854 },
855 rpc_middleware,
856 };
857
858 let service = http_middleware.service(tower_service);
859
860 let serve = async move {
861 let request_received = Arc::new(Notify::new());
862 let service = NotifyOnRequest::new(
864 TowerToHyperService::new(
865 service.map_request(|request: HttpRequest<Incoming>| request.map(HttpBody::new)),
866 ),
867 request_received.clone(),
868 );
869 let io = TokioIo::new(WriteTimeoutIo::new(socket, write_timeout));
870 let builder = hyper_util::server::conn::auto::Builder::new(TokioExecutor::new());
871 let conn = builder.serve_connection_with_upgrades(io, service);
872 let stopped = stop_handle.shutdown();
873
874 tokio::pin!(stopped, conn);
875
876 let res = tokio::select! {
877 res = &mut conn => res,
878 _ = &mut stopped => {
879 conn.as_mut().graceful_shutdown();
882 conn.await
883 }
884 err = no_request_within(&request_received, first_request_timeout) => Err(err),
885 };
886
887 if let Err(e) = res {
888 tracing::debug!(target: LOG_TARGET, "HTTP serve connection failed {:?}", e);
889 }
890 drop(drop_on_completion)
891 };
892 tokio::spawn(serve.in_current_span());
894}
895
896enum AcceptConnection<S> {
897 Shutdown,
898 Established { socket: TcpStream, remote_addr: SocketAddr, stop: S },
899 Err((std::io::Error, S)),
900}
901
902async fn try_accept_conn<S>(listener: &TcpListener, stopped: S) -> AcceptConnection<S>
903where
904 S: Future + Unpin,
905{
906 let accept = listener.accept();
907 tokio::pin!(accept);
908
909 match futures_util::future::select(stopped, accept).await {
913 Either::Left(_) => AcceptConnection::Shutdown,
914 Either::Right((res, stop)) => match res {
915 Ok((socket, remote_addr)) => {
916 AcceptConnection::Established { socket, remote_addr, stop }
917 }
918 Err(e) => AcceptConnection::Err((e, stop)),
919 },
920 }
921}
922
923pub async fn handle_rpc_call<S>(
930 body: &[u8],
931 is_single: bool,
932 batch_config: BatchRequestConfig,
933 rpc_service: &S,
934) -> MethodResponse
935where
936 S: RpcServiceT + Send,
937{
938 if is_single {
940 if let Ok(req) = serde_json::from_slice::<Request<'_>>(body) {
941 catch_call_panic(req.id(), || rpc_service.call(req)).await
942 } else if let Ok(notif) = deserialize_notification(body) {
943 rpc_service.notification(notif).await
944 } else {
945 let (id, code) = prepare_error(body);
946 MethodResponse::error(id, ErrorObject::from(code))
947 }
948 }
949 else {
951 let max_len = match batch_config {
952 BatchRequestConfig::Disabled => {
953 let rp = MethodResponse::error(
954 Id::Null,
955 ErrorObject::borrowed(
956 BATCHES_NOT_SUPPORTED_CODE,
957 BATCHES_NOT_SUPPORTED_MSG,
958 None,
959 ),
960 );
961 return rp;
962 }
963 BatchRequestConfig::Limit(limit) => limit as usize,
964 BatchRequestConfig::Unlimited => usize::MAX,
965 };
966
967 match parse_batch(body, max_len) {
968 Ok(batch) => rpc_service.batch(batch).await,
969 Err(rp) => rp,
970 }
971 }
972}
973
974fn parse_batch(body: &[u8], max_len: usize) -> Result<Batch<'_>, MethodResponse> {
977 let mut entries = Vec::new();
978 let mut too_big = false;
979
980 for raw in [false, true] {
984 let mut deserializer = serde_json::Deserializer::from_slice(body);
985 let read = BatchSeed { max_len, too_big: &mut too_big, entries: &mut entries, raw }
986 .deserialize(&mut deserializer)
987 .and_then(|()| deserializer.end());
988
989 if read.is_ok() {
990 return Ok(Batch::from(entries));
991 }
992 if too_big {
995 return Err(MethodResponse::error(Id::Null, reject_too_big_batch_request(max_len)));
996 }
997 }
998
999 Err(MethodResponse::error(Id::Null, ErrorObject::from(ErrorCode::ParseError)))
1000}
1001
1002fn parse_batch_entry(call: &JsonRawValue) -> Result<BatchEntry<'_>, BatchEntryErr<'_>> {
1004 if !call.get().starts_with('{') {
1007 return Err(BatchEntryErr::new(Id::Null, ErrorCode::InvalidRequest.into()));
1008 }
1009
1010 if let Ok(req) = serde_json::from_str(call.get()) {
1011 Ok(BatchEntry::Call(req))
1012 } else if let Ok(notif) = deserialize_notification(call.get().as_bytes()) {
1013 Ok(BatchEntry::Notification(notif))
1014 } else {
1015 let id = match serde_json::from_str::<jsonrpsee_types::InvalidRequest>(call.get()) {
1016 Ok(err) => err.id,
1017 Err(_) => Id::Null,
1018 };
1019
1020 Err(BatchEntryErr::new(id, ErrorCode::InvalidRequest.into()))
1021 }
1022}
1023
1024#[derive(Deserialize)]
1028#[serde(deny_unknown_fields)]
1029struct ValidBatchEntry<'a> {
1030 jsonrpc: TwoPointZero,
1031 #[serde(borrow, default, deserialize_with = "deserialize_present_id")]
1032 id: Option<Id<'a>>,
1033 #[serde(borrow)]
1034 method: Cow<'a, str>,
1035 #[serde(borrow)]
1036 params: Option<&'a JsonRawValue>,
1037}
1038
1039impl<'a> From<ValidBatchEntry<'a>> for BatchEntry<'a> {
1040 fn from(entry: ValidBatchEntry<'a>) -> Self {
1041 let ValidBatchEntry { jsonrpc, id, method, params } = entry;
1042 let params = params.map(Cow::Borrowed);
1043 match id {
1044 Some(id) => Self::Call(Request { jsonrpc, id, method, params }),
1045 None => Self::Notification(Notification::new(method, params)),
1046 }
1047 }
1048}
1049
1050fn deserialize_present_id<'de, D: Deserializer<'de>>(
1052 deserializer: D,
1053) -> Result<Option<Id<'de>>, D::Error> {
1054 Id::deserialize(deserializer).map(Some)
1055}
1056
1057struct ValidBatchEntrySeed;
1060
1061impl<'de> DeserializeSeed<'de> for ValidBatchEntrySeed {
1062 type Value = ValidBatchEntry<'de>;
1063
1064 fn deserialize<D: Deserializer<'de>>(self, deserializer: D) -> Result<Self::Value, D::Error> {
1065 deserializer.deserialize_map(self)
1066 }
1067}
1068
1069impl<'de> Visitor<'de> for ValidBatchEntrySeed {
1070 type Value = ValidBatchEntry<'de>;
1071
1072 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1073 formatter.write_str("a JSON-RPC request object")
1074 }
1075
1076 fn visit_map<A: MapAccess<'de>>(self, map: A) -> Result<Self::Value, A::Error> {
1077 ValidBatchEntry::deserialize(MapAccessDeserializer::new(map))
1078 }
1079}
1080
1081struct BatchSeed<'a, 'de> {
1089 max_len: usize,
1090 too_big: &'a mut bool,
1091 entries: &'a mut Vec<Result<BatchEntry<'de>, BatchEntryErr<'de>>>,
1092 raw: bool,
1093}
1094
1095impl<'de> DeserializeSeed<'de> for BatchSeed<'_, 'de> {
1096 type Value = ();
1097
1098 fn deserialize<D: Deserializer<'de>>(self, deserializer: D) -> Result<Self::Value, D::Error> {
1099 deserializer.deserialize_seq(self)
1100 }
1101}
1102
1103impl<'de> Visitor<'de> for BatchSeed<'_, 'de> {
1104 type Value = ();
1105
1106 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1107 formatter.write_str("a batch of JSON-RPC requests")
1108 }
1109
1110 fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
1111 if self.raw {
1112 for _ in 0..self.entries.len() {
1113 seq.next_element::<IgnoredAny>()?;
1114 }
1115 }
1116
1117 loop {
1118 if self.entries.len() == self.max_len {
1119 if seq.next_element::<&'de JsonRawValue>()?.is_some() {
1121 *self.too_big = true;
1122 return Err(A::Error::custom("batch too big"));
1123 }
1124 return Ok(());
1125 }
1126
1127 let entry = if self.raw {
1128 seq.next_element::<&'de JsonRawValue>()?.map(parse_batch_entry)
1129 } else {
1130 seq.next_element_seed(ValidBatchEntrySeed)?.map(|entry| Ok(entry.into()))
1131 };
1132 let Some(entry) = entry else { return Ok(()) };
1133
1134 self.entries.push(entry);
1136 }
1137 }
1138}
1139
1140#[cfg(test)]
1141mod tests {
1142 use super::*;
1143 use futures_util::future;
1144 use test_case::test_case;
1145
1146 const CALL: &str = r#"{"jsonrpc":"2.0","method":"m","params":[1],"id":1}"#;
1147
1148 const NOTIFICATION: &str = r#"{"jsonrpc":"2.0","method":"m"}"#;
1149
1150 fn classify_raw_batch(body: &str, max_len: usize) -> Option<String> {
1152 let (mut entries, mut too_big) = (Vec::new(), false);
1153 let mut deserializer = serde_json::Deserializer::from_str(body);
1154 BatchSeed { max_len, too_big: &mut too_big, entries: &mut entries, raw: true }
1155 .deserialize(&mut deserializer)
1156 .and_then(|()| deserializer.end())
1157 .ok()
1158 .map(|()| format!("{entries:?}"))
1159 }
1160
1161 #[tokio::test]
1162 async fn try_accept_conn_observes_stop_before_a_waiting_connection() {
1163 let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
1164 let addr = listener.local_addr().unwrap();
1165
1166 let _client = TcpStream::connect(addr).await.unwrap();
1167 tokio::time::sleep(Duration::from_millis(50)).await;
1170
1171 let accepted = try_accept_conn(&listener, future::ready(())).await;
1172 assert!(matches!(accepted, AcceptConnection::Shutdown));
1173 }
1174
1175 #[test_case(&[CALL, CALL], usize::MAX; "calls")]
1176 #[test_case(&[CALL, NOTIFICATION, r#"{"jsonrpc":"2.0","method":"m","id":null}"#], usize::MAX; "call, notification and null id")]
1177 #[test_case(&[r#"{"id":"a","params":null,"method":"\"m\"","x":1,"jsonrpc":"2.0"}"#], usize::MAX; "escaped method, null params and unknown member")]
1178 #[test_case(&[CALL, r#"{"jsonrpc":"2.0","id":2}"#, NOTIFICATION, CALL], usize::MAX; "missing method between valid entries")]
1179 #[test_case(&[r#"{"jsonrpc":"1.0","method":"m","id":3}"#, CALL], usize::MAX; "wrong version first")]
1180 #[test_case(&[CALL, r#"{"jsonrpc":"2.0","method":"m","id":{}}"#], usize::MAX; "object id")]
1181 #[test_case(&[CALL, r#"{"jsonrpc":"2.0","method":"m","id":1,"id":2}"#], usize::MAX; "duplicate id")]
1182 #[test_case(&[CALL, r#"["2.0",2,"m",[]]"#, "7", CALL], usize::MAX; "array and number entries")]
1183 #[test_case(&[CALL, r#"{"id":2}"#], 2; "invalid entry at the limit")]
1184 #[test_case(&[CALL, r#"{"id":2}"#, CALL], 2; "valid entry past the limit")]
1185 #[test_case(&[CALL, CALL, r#"{"id":2}"#], 2; "invalid entry past the limit")]
1186 #[test_case(&[CALL, r#"{"jsonrpc""#], usize::MAX; "not json")]
1187 fn batch_entries_decode_like_their_raw_json(entries: &[&str], max_len: usize) {
1188 let body = format!("[{}]", entries.join(","));
1189 let batch = parse_batch(body.as_bytes(), max_len)
1190 .ok()
1191 .map(|batch| format!("{:?}", batch.into_iter().collect::<Vec<_>>()));
1192 assert_eq!(batch, classify_raw_batch(&body, max_len));
1193 }
1194
1195 #[test]
1196 fn batch_with_invalid_utf8_is_a_parse_error() {
1197 let body = b"[{\"jsonrpc\":\"2.0\",\"method\":\"m\",\"id\":1,\"x\":\"\xff\"}]";
1199 let rp = parse_batch(body, usize::MAX).unwrap_err();
1200 assert_eq!(rp.as_error_code(), Some(ErrorCode::ParseError.code()));
1201 }
1202
1203 #[test]
1204 fn valid_batch_entries_are_calls_or_notifications() {
1205 let body = br#"[{"jsonrpc":"2.0","method":"a","id":null},{"jsonrpc":"2.0","method":"b"}]"#;
1206 let batch = parse_batch(body, usize::MAX).unwrap().into_iter().collect::<Vec<_>>();
1207 assert!(matches!(
1208 batch.as_slice(),
1209 [Ok(BatchEntry::Call(call)), Ok(BatchEntry::Notification(notification))]
1210 if call.id == Id::Null && call.method == "a" && notification.method == "b"
1211 ));
1212 }
1213
1214 #[test_case(&[CALL.as_bytes(), CALL.as_bytes(), b"\"\xff\""], 1, reject_too_big_batch_request(1); "invalid utf8 after excess call")]
1215 #[test_case(&[br#"{"id":2}"#, CALL.as_bytes(), b"\"\xff\""], 1, reject_too_big_batch_request(1); "invalid utf8 after fallback exceeds limit")]
1216 #[test_case(&[CALL.as_bytes(), b"\"\xff\""], 1, ErrorCode::ParseError.into(); "invalid utf8 in excess entry")]
1217 #[test_case(&[b"{\"jsonrpc\":\"2.0\",\"method\":\"m\",\"x\":\"\xff\"}", CALL.as_bytes()], 1, ErrorCode::ParseError.into(); "invalid utf8 before excess entry")]
1218 #[test_case(&[CALL.as_bytes(), br#"{"jsonrpc"#], 1, ErrorCode::ParseError.into(); "malformed excess entry")]
1219 #[test_case(&[CALL.as_bytes(), b"7", b"\"\xff\""], 1, reject_too_big_batch_request(1); "invalid utf8 after excess scalar")]
1220 #[test_case(&[CALL.as_bytes(), b"\"\xff\""], 0, reject_too_big_batch_request(0); "zero limit ignores tail")]
1221 fn batch_limit_preserves_parse_errors(
1222 entries: &[&[u8]],
1223 max_len: usize,
1224 expected: ErrorObject<'_>,
1225 ) {
1226 let body = [b"[".as_slice(), entries.join(b",".as_slice()).as_slice(), b"]"].concat();
1227 assert_eq!(
1228 parse_batch(&body, max_len).unwrap_err().into_json(),
1229 MethodResponse::error(Id::Null, expected).into_json()
1230 );
1231 }
1232
1233 #[test_case(b"[]", 0; "empty batch")]
1234 #[test_case(b"[{\"jsonrpc\":\"2.0\",\"method\":\"m\"}]", 1; "notification")]
1235 fn batch_at_limit_is_accepted(body: &[u8], max_len: usize) {
1236 assert_eq!(parse_batch(body, max_len).unwrap().len(), max_len);
1237 }
1238}