11use std:: collections:: HashMap ;
22use std:: ffi:: OsStr ;
33use std:: io;
4- use std:: rc :: Rc ;
4+ use std:: sync :: { Arc , Mutex } ;
55
6+ use http_body_util:: Full ;
7+ use hyper:: body:: { Bytes , Incoming } ;
8+ use hyper:: { Request , Response } ;
69use libloading:: Library ;
710
811use http_server_plugin:: {
@@ -12,74 +15,83 @@ use http_server_plugin::{
1215/// A proxy object which wraps a [`Function`] and makes sure it can't outlive
1316/// the library it came from.
1417pub struct FunctionProxy {
15- function : Box < dyn Function > ,
16- _lib : Rc < Library > ,
18+ function : Arc < dyn Function > ,
19+ _lib : Arc < Library > ,
1720}
1821
1922impl Function for FunctionProxy {
20- fn call ( & self , args : & [ f64 ] ) -> Result < f64 , InvocationError > {
21- self . function . call ( args)
22- }
23-
24- fn help ( & self ) -> Option < & str > {
25- self . function . help ( )
23+ fn call ( & self , req : Request < Incoming > ) -> Result < Response < Full < Bytes > > , InvocationError > {
24+ self . function . call ( req)
2625 }
2726}
2827
2928#[ derive( Default ) ]
3029pub struct ExternalFunctions {
31- functions : HashMap < String , FunctionProxy > ,
32- libraries : Vec < Rc < Library > > ,
30+ functions : Mutex < HashMap < String , FunctionProxy > > ,
31+ libraries : Mutex < Vec < Arc < Library > > > ,
3332}
3433
3534impl ExternalFunctions {
3635 pub fn new ( ) -> ExternalFunctions {
3736 ExternalFunctions :: default ( )
3837 }
3938
40- pub unsafe fn load < P : AsRef < OsStr > > ( & mut self , library_path : P ) -> io:: Result < ( ) > {
41- // load the library into memory
42- let library = Rc :: new ( Library :: new ( library_path) . unwrap ( ) ) ;
43-
44- // get a pointer to the plugin_declaration symbol.
39+ /// Loads a plugin from the given path.
40+ ///
41+ /// # Safety
42+ ///
43+ /// This function is unsafe because it loads a shared library and calls
44+ /// functions from it.
45+ pub unsafe fn load < P : AsRef < OsStr > > ( & self , library_path : P ) -> io:: Result < ( ) > {
46+ let library = Arc :: new ( Library :: new ( library_path) . unwrap ( ) ) ;
4547 let decl = library
4648 . get :: < * mut PluginDeclaration > ( b"plugin_declaration\0 " )
4749 . unwrap ( )
4850 . read ( ) ;
4951
50- // version checks to prevent accidental ABI incompatibilities
5152 if decl. rustc_version != RUSTC_VERSION || decl. core_version != CORE_VERSION {
5253 return Err ( io:: Error :: new ( io:: ErrorKind :: Other , "Version mismatch" ) ) ;
5354 }
5455
55- let mut registrar = PluginRegistrar :: new ( Rc :: clone ( & library) ) ;
56+ let mut registrar = PluginRegistrar :: new ( Arc :: clone ( & library) ) ;
5657
5758 ( decl. register ) ( & mut registrar) ;
5859
59- // add all loaded plugins to the functions map
60- self . functions . extend ( registrar. functions ) ;
61- // and make sure ExternalFunctions keeps a reference to the library
62- self . libraries . push ( library) ;
60+ self . functions
61+ . lock ( )
62+ . expect ( "Cannot lock Mutex" )
63+ . extend ( registrar. functions ) ;
64+
65+ self . libraries
66+ . lock ( )
67+ . expect ( "Cannot lock Mutex" )
68+ . push ( library) ;
6369
6470 Ok ( ( ) )
6571 }
6672
67- pub fn call ( & self , function : & str , arguments : & [ f64 ] ) -> Result < f64 , InvocationError > {
73+ pub fn call (
74+ & self ,
75+ function : & str ,
76+ req : Request < Incoming > ,
77+ ) -> Result < Response < Full < Bytes > > , InvocationError > {
6878 self . functions
79+ . lock ( )
80+ . expect ( "Cannot lock Mutex" )
6981 . get ( function)
7082 . ok_or_else ( || format ! ( "\" {}\" not found" , function) )
7183 . unwrap ( )
72- . call ( arguments )
84+ . call ( req )
7385 }
7486}
7587
7688struct PluginRegistrar {
7789 functions : HashMap < String , FunctionProxy > ,
78- lib : Rc < Library > ,
90+ lib : Arc < Library > ,
7991}
8092
8193impl PluginRegistrar {
82- fn new ( lib : Rc < Library > ) -> PluginRegistrar {
94+ fn new ( lib : Arc < Library > ) -> PluginRegistrar {
8395 PluginRegistrar {
8496 lib,
8597 functions : HashMap :: default ( ) ,
@@ -88,10 +100,10 @@ impl PluginRegistrar {
88100}
89101
90102impl http_server_plugin:: PluginRegistrar for PluginRegistrar {
91- fn register_function ( & mut self , name : & str , function : Box < dyn Function > ) {
103+ fn register_function ( & mut self , name : & str , function : Arc < dyn Function > ) {
92104 let proxy = FunctionProxy {
93105 function,
94- _lib : Rc :: clone ( & self . lib ) ,
106+ _lib : Arc :: clone ( & self . lib ) ,
95107 } ;
96108
97109 self . functions . insert ( name. to_string ( ) , proxy) ;
0 commit comments