@@ -444,11 +444,10 @@ use fvm_ipld_blockstore::Blockstore;
444444use jsonrpsee:: {
445445 Methods ,
446446 core:: middleware:: RpcServiceBuilder ,
447- server:: { RpcModule , Server , StopHandle , TowerServiceBuilder , stop_channel } ,
447+ server:: { RpcModule , Server , StopHandle , TowerServiceBuilder } ,
448448} ;
449449use parking_lot:: RwLock ;
450450use std:: env;
451- use std:: net:: SocketAddr ;
452451use std:: sync:: { Arc , LazyLock } ;
453452use std:: time:: Duration ;
454453use tokio:: sync:: mpsc;
@@ -530,7 +529,8 @@ struct PerConnection<RpcMiddleware, HttpMiddleware> {
530529
531530pub async fn start_rpc < DB > (
532531 state : RPCState < DB > ,
533- rpc_endpoint : SocketAddr ,
532+ rpc_listener : tokio:: net:: TcpListener ,
533+ stop_handle : StopHandle ,
534534 filter_list : Option < FilterList > ,
535535) -> anyhow:: Result < ( ) >
536536where
@@ -557,8 +557,6 @@ where
557557 let methods: Arc < HashMap < ApiPaths , Methods > > =
558558 Arc :: new ( modules. into_iter ( ) . map ( |( k, v) | ( k, v. into ( ) ) ) . collect ( ) ) ;
559559
560- let ( stop_handle, _server_handle) = stop_channel ( ) ;
561-
562560 let per_conn = PerConnection {
563561 stop_handle : stop_handle. clone ( ) ,
564562 svc_builder : Server :: builder ( )
@@ -581,12 +579,10 @@ where
581579 . to_service_builder ( ) ,
582580 keystore,
583581 } ;
584-
585- let listener = tokio:: net:: TcpListener :: bind ( rpc_endpoint) . await . unwrap ( ) ;
586582 tracing:: info!( "Ready for RPC connections" ) ;
587583 loop {
588584 let sock = tokio:: select! {
589- res = listener . accept( ) => {
585+ res = rpc_listener . accept( ) => {
590586 match res {
591587 Ok ( ( stream, _remote_addr) ) => stream,
592588 Err ( e) => {
@@ -789,7 +785,14 @@ pub fn openrpc(path: ApiPaths, include: Option<&[&str]>) -> openrpc_types::OpenR
789785
790786#[ cfg( test) ]
791787mod tests {
792- use crate :: rpc:: ApiPaths ;
788+ use super :: * ;
789+ use crate :: {
790+ db:: MemoryDB , networks:: NetworkChain , rpc:: common:: ShiftingVersion ,
791+ tool:: offline_server:: server:: offline_rpc_state,
792+ } ;
793+ use jsonrpsee:: server:: stop_channel;
794+ use std:: net:: { Ipv4Addr , SocketAddr } ;
795+ use tokio:: task:: JoinSet ;
793796
794797 // `cargo test --lib -- --exact 'rpc::tests::openrpc'`
795798 // `cargo insta review`
@@ -808,4 +811,62 @@ mod tests {
808811 insta:: assert_yaml_snapshot!( _spec) ;
809812 }
810813 }
814+
815+ #[ tokio:: test( flavor = "multi_thread" ) ]
816+ async fn test_rpc_server ( ) {
817+ let chain = NetworkChain :: Calibnet ;
818+ let db = Arc :: new ( MemoryDB :: default ( ) ) ;
819+ let mut services = JoinSet :: new ( ) ;
820+ let ( state, mut shutdown_recv) = offline_rpc_state ( chain, db, None , None , & mut services)
821+ . await
822+ . unwrap ( ) ;
823+ let block_delay_secs = state. chain_config ( ) . block_delay_secs ;
824+ let shutdown_send = state. shutdown . clone ( ) ;
825+ let jwt_read_permissions = vec ! [ "read" . to_owned( ) ] ;
826+ let jwt_read = super :: methods:: auth:: AuthNew :: create_token (
827+ & state. keystore . read ( ) ,
828+ chrono:: Duration :: hours ( 1 ) ,
829+ jwt_read_permissions. clone ( ) ,
830+ )
831+ . unwrap ( ) ;
832+ let rpc_listener =
833+ tokio:: net:: TcpListener :: bind ( SocketAddr :: new ( Ipv4Addr :: LOCALHOST . into ( ) , 0 ) )
834+ . await
835+ . unwrap ( ) ;
836+ let rpc_address = rpc_listener. local_addr ( ) . unwrap ( ) ;
837+ let ( stop_handle, server_handle) = stop_channel ( ) ;
838+
839+ // Start an RPC server
840+
841+ let handle = tokio:: spawn ( start_rpc ( state, rpc_listener, stop_handle, None ) ) ;
842+
843+ // Send a few requests
844+
845+ let client = Client :: from_url (
846+ format ! ( "http://{}:{}/" , rpc_address. ip( ) , rpc_address. port( ) )
847+ . parse ( )
848+ . unwrap ( ) ,
849+ ) ;
850+
851+ let response = super :: methods:: common:: Version :: call ( & client, ( ) )
852+ . await
853+ . unwrap ( ) ;
854+ assert_eq ! (
855+ & response. version,
856+ & * crate :: utils:: version:: FOREST_VERSION_STRING
857+ ) ;
858+ assert_eq ! ( response. block_delay, block_delay_secs) ;
859+ assert_eq ! ( response. api_version, ShiftingVersion :: new( 2 , 3 , 0 ) ) ;
860+
861+ let response = super :: methods:: auth:: AuthVerify :: call ( & client, ( jwt_read, ) )
862+ . await
863+ . unwrap ( ) ;
864+ assert_eq ! ( response, jwt_read_permissions) ;
865+
866+ // Gracefully shutdown the RPC server
867+ shutdown_send. send ( ( ) ) . await . unwrap ( ) ;
868+ shutdown_recv. recv ( ) . await ;
869+ server_handle. stop ( ) . unwrap ( ) ;
870+ handle. await . unwrap ( ) . unwrap ( ) ;
871+ }
811872}
0 commit comments