2626
2727use futures_channel:: mpsc;
2828use futures_util:: io:: { BufReader , BufWriter } ;
29+ use futures_util:: stream:: StreamExt ;
2930use parking_lot:: Mutex ;
3031use rustc_hash:: FxHashMap ;
3132use serde:: Serialize ;
@@ -34,14 +35,14 @@ use soketto::handshake::{server::Response, Server as SokettoServer};
3435use std:: net:: SocketAddr ;
3536use std:: sync:: Arc ;
3637use tokio:: net:: { TcpListener , ToSocketAddrs } ;
37- use tokio_stream:: { wrappers:: TcpListenerStream , StreamExt } ;
38+ use tokio_stream:: wrappers:: TcpListenerStream ;
3839use tokio_util:: compat:: TokioAsyncReadCompatExt ;
3940
40- use jsonrpsee_types:: error:: { Error , InvalidParams } ;
41+ use jsonrpsee_types:: error:: { CallError , Error } ;
4142use jsonrpsee_types:: v2:: error:: JsonRpcErrorCode ;
4243use jsonrpsee_types:: v2:: params:: { JsonRpcNotificationParams , RpcParams , TwoPointZero } ;
4344use jsonrpsee_types:: v2:: request:: { JsonRpcInvalidRequest , JsonRpcNotification , JsonRpcRequest } ;
44- use jsonrpsee_utils:: server:: { send_error, ConnectionId , Methods } ;
45+ use jsonrpsee_utils:: server:: { collect_batch_response , send_error, ConnectionId , Methods , RpcSender } ;
4546
4647mod module;
4748
@@ -105,7 +106,7 @@ impl Server {
105106 pub fn register_method < F , R > ( & mut self , method_name : & ' static str , callback : F ) -> Result < ( ) , Error >
106107 where
107108 R : Serialize ,
108- F : Fn ( RpcParams ) -> Result < R , InvalidParams > + Send + Sync + ' static ,
109+ F : Fn ( RpcParams ) -> Result < R , CallError > + Send + Sync + ' static ,
109110 {
110111 self . root . register_method ( method_name, callback)
111112 }
@@ -149,7 +150,11 @@ impl Server {
149150 }
150151}
151152
152- async fn background_task ( socket : tokio:: net:: TcpStream , methods : Arc < Methods > , id : ConnectionId ) -> anyhow:: Result < ( ) > {
153+ async fn background_task (
154+ socket : tokio:: net:: TcpStream ,
155+ methods : Arc < Methods > ,
156+ conn_id : ConnectionId ,
157+ ) -> anyhow:: Result < ( ) > {
153158 // For each incoming background_task we perform a handshake.
154159 let mut server = SokettoServer :: new ( BufReader :: new ( BufWriter :: new ( socket. compat ( ) ) ) ) ;
155160
@@ -166,38 +171,69 @@ async fn background_task(socket: tokio::net::TcpStream, methods: Arc<Methods>, i
166171 let ( mut sender, mut receiver) = server. into_builder ( ) . finish ( ) ;
167172 let ( tx, mut rx) = mpsc:: unbounded :: < String > ( ) ;
168173
174+ // Send results back to the client.
169175 tokio:: spawn ( async move {
170176 while let Some ( response) = rx. next ( ) . await {
171177 let _ = sender. send_binary_mut ( response. into_bytes ( ) ) . await ;
172178 let _ = sender. flush ( ) . await ;
173179 }
174180 } ) ;
175181
176- let mut data = Vec :: new ( ) ;
182+ let mut data = Vec :: with_capacity ( 100 ) ;
183+
184+ // Look up the "method" (i.e. function pointer) from the registered methods and run it passing in
185+ // the params from the request. The result of the computation is sent back over the `tx` channel and
186+ // the result(s) are collected into a `String` and sent back over the wire.
187+ let execute = move |tx : RpcSender , req : JsonRpcRequest | {
188+ if let Some ( method) = methods. get ( & * req. method ) {
189+ let params = RpcParams :: new ( req. params . map ( |params| params. get ( ) ) ) ;
190+ if let Err ( err) = ( method) ( req. id , params, & tx, conn_id) {
191+ log:: error!( "execution of method call '{}' failed: {:?}, request id={:?}" , req. method, err, req. id) ;
192+ send_error ( req. id , & tx, JsonRpcErrorCode :: ServerError ( -1 ) . into ( ) ) ;
193+ }
194+ } else {
195+ send_error ( req. id , & tx, JsonRpcErrorCode :: MethodNotFound . into ( ) ) ;
196+ }
197+ } ;
177198
178199 loop {
179200 data. clear ( ) ;
180201
181202 receiver. receive_data ( & mut data) . await ?;
182203
183- match serde_json:: from_slice :: < JsonRpcRequest > ( & data) {
184- Ok ( req) => {
185- let params = RpcParams :: new ( req. params . map ( |params| params. get ( ) ) ) ;
186-
187- if let Some ( method) = methods. get ( & * req. method ) {
188- ( method) ( req. id , params, & tx, id) ?;
189- } else {
190- send_error ( req. id , & tx, JsonRpcErrorCode :: MethodNotFound . into ( ) ) ;
204+ // For reasons outlined [here](https://github.com/serde-rs/json/issues/497), `RawValue` can't be used with
205+ // untagged enums at the moment. This means we can't use an `SingleOrBatch` untagged enum here and have to try
206+ // each case individually: first the single request case, then the batch case and lastly the error. For the
207+ // worst case – unparseable input – we make three calls to [`serde_json::from_slice`] which is pretty annoying.
208+ // Our [issue](https://github.com/paritytech/jsonrpsee/issues/296).
209+ if let Ok ( req) = serde_json:: from_slice :: < JsonRpcRequest > ( & data) {
210+ execute ( & tx, req) ;
211+ } else if let Ok ( batch) = serde_json:: from_slice :: < Vec < JsonRpcRequest > > ( & data) {
212+ if !batch. is_empty ( ) {
213+ // Batch responses must be sent back as a single message so we read the results from each request in the
214+ // batch and read the results off of a new channel, `rx_batch`, and then send the complete batch response
215+ // back to the client over `tx`.
216+ let ( tx_batch, mut rx_batch) = mpsc:: unbounded :: < String > ( ) ;
217+ for req in batch {
218+ execute ( & tx_batch, req) ;
219+ }
220+ // Closes the receiving half of a channel without dropping it. This prevents any further messages from
221+ // being sent on the channel.
222+ rx_batch. close ( ) ;
223+ let results = collect_batch_response ( rx_batch) . await ;
224+ if let Err ( err) = tx. unbounded_send ( results) {
225+ log:: error!( "Error sending batch response to the client: {:?}" , err)
191226 }
227+ } else {
228+ send_error ( None , & tx, JsonRpcErrorCode :: InvalidRequest . into ( ) ) ;
192229 }
193- Err ( _ ) => {
194- let ( id, code) = match serde_json:: from_slice :: < JsonRpcInvalidRequest > ( & data) {
195- Ok ( req) => ( req. id , JsonRpcErrorCode :: InvalidRequest ) ,
196- Err ( _) => ( None , JsonRpcErrorCode :: ParseError ) ,
197- } ;
230+ } else {
231+ let ( id, code) = match serde_json:: from_slice :: < JsonRpcInvalidRequest > ( & data) {
232+ Ok ( req) => ( req. id , JsonRpcErrorCode :: InvalidRequest ) ,
233+ Err ( _) => ( None , JsonRpcErrorCode :: ParseError ) ,
234+ } ;
198235
199- send_error ( id, & tx, code. into ( ) ) ;
200- }
236+ send_error ( id, & tx, code. into ( ) ) ;
201237 }
202238 }
203239}
0 commit comments