packages feed

capnp 0.5.0.0 → 0.6.0.0

raw patch · 14 files changed

+260/−49 lines, 14 filesdep ~basePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base

API changes (from Hackage documentation)

+ Capnp.Gen.Capnp.Persistent.Pure: instance Capnp.Rpc.Server.Server GHC.Types.IO Capnp.Gen.Capnp.Persistent.Pure.Persistent
+ Capnp.Gen.Capnp.Persistent.Pure: instance Capnp.Rpc.Server.Server GHC.Types.IO Capnp.Gen.Capnp.Persistent.Pure.RealmGateway
+ Capnp.Rpc: class Monad m => Server m a | a -> m
+ Capnp.Rpc: shutdown :: Server m a => a -> m ()
+ Capnp.Rpc: unwrap :: (Server m a, Typeable b) => a -> Maybe b
+ Capnp.Rpc: unwrapServer :: (IsClient c, Typeable a) => c -> Maybe a
+ Capnp.Rpc.Server: [handleCast] :: ServerOps m -> forall a. Typeable a => Maybe a
+ Capnp.Rpc.Server: class Monad m => Server m a | a -> m
+ Capnp.Rpc.Server: shutdown :: Server m a => a -> m ()
+ Capnp.Rpc.Server: unwrap :: (Server m a, Typeable b) => a -> Maybe b
+ Capnp.Rpc.Untyped: unwrapServer :: (IsClient c, Typeable a) => c -> Maybe a
- Capnp.Gen.Capnp.Persistent.Pure: class ((MonadIO m)) => Persistent'server_ m cap
+ Capnp.Gen.Capnp.Persistent.Pure: class ((MonadIO m), (Server m cap)) => Persistent'server_ m cap
- Capnp.Gen.Capnp.Persistent.Pure: class ((MonadIO m)) => RealmGateway'server_ m cap
+ Capnp.Gen.Capnp.Persistent.Pure: class ((MonadIO m), (Server m cap)) => RealmGateway'server_ m cap
- Capnp.Rpc.Server: ServerOps :: (Word64 -> Word16 -> MethodHandler m (Maybe (Ptr ConstMsg)) (Maybe (Ptr ConstMsg))) -> m () -> ServerOps m
+ Capnp.Rpc.Server: ServerOps :: (Word64 -> Word16 -> MethodHandler m (Maybe (Ptr ConstMsg)) (Maybe (Ptr ConstMsg))) -> m () -> (forall a. Typeable a => Maybe a) -> ServerOps m

Files

CHANGELOG.md view
@@ -1,3 +1,18 @@+# 0.6.0.0++## RPC++* Fix a serious bug in `newPromiseClient`, resulting in dropped calls+  made on the promise before it is resolved.+* There is now a `Server` class, which all RPC servers must implement.+  All of its methods have default implementations, so adding an instance+  to existing servers is straightforward.+* It is now possible to "unwrap" clients that point to a local server+  using the new 'Capnp.Rpc.unwrapServer' function, if the server+  implements support for it with the new 'Server' type class.+* Servers can now specify a hook to be run when the server is shut down,+  using the server class's 'shutdown' method.+ # 0.5.0.0  ## Serialization
capnp.cabal view
@@ -1,6 +1,6 @@ cabal-version:            2.2 name:                     capnp-version:                  0.5.0.0+version:                  0.6.0.0 category:                 Data, Serialization, Network, Rpc copyright:                2016-2020 haskell-capnp contributors (see CONTRIBUTORS file). author:                   Ian Denhardt@@ -270,6 +270,7 @@       , WalkSchemaCodeGenRequest       , SchemaQuickCheck       , CalculatorExample+      , Rpc.Unwrap     build-depends:         capnp       , network
cmd/capnpc-haskell/Trans/PureToHaskell.hs view
@@ -48,6 +48,7 @@     , ImportAs { importAs = "Supervisors", parts = reExp ["Supervisors"] }     ] +reExp :: [Name.UnQ] -> [Name.UnQ] reExp parts = ["Capnp", "GenHelpers", "ReExports"] ++ parts  -- | Whether the serialized and unserialized forms of this type@@ -426,13 +427,20 @@ ifaceClassDecl thisMod P.IFace { name=Name.CapnpQ{local=name}, methods, supers } =     DcClass         { ctx =+            let superConstraints =+                    -- Add class constraints for superclasses:+                    [ let superClass = pureTName thisMod fileId (Name.mkSub local "server_")+                      in TApp superClass [tuName "m", tuName "cap"]+                    | P.IFace{name=Name.CapnpQ{local, fileId}} <- supers+                    ]+            in             TApp (tgName ["MonadIO"] "MonadIO") [tuName "m"]-            :-            -- Add class constraints for superclasses:-            [ let superClass = pureTName thisMod fileId (Name.mkSub local "server_")-              in TApp superClass [tuName "m", tuName "cap"]-            | P.IFace{name=Name.CapnpQ{local, fileId}} <- supers-            ]+            : case superConstraints of+                -- If this interface doesn't have any superclasses, then we need to+                -- specify a constraint for the 'Server' class. Otherwise, it's+                -- implied by the supers.+                [] -> [ TApp (tgName ["Server"] "Server") [tuName "m", tuName "cap"] ]+                _ -> superConstraints         , name = Name.mkSub name "server_"         , params = ["m", "cap"]         , decls =@@ -488,9 +496,12 @@                 [ EApp (egName ["Rpc"] "export")                     [ euName "sup_"                     , ERecord (egName ["Server"] "ServerOps")-                        [ ( "handleStop"-                          , ePureUnit-                          ) -- TODO+                        [ ( "handleCast"+                          , EApp (egName ["Server"] "unwrap") [ELName "server_"]+                          )+                        , ( "handleStop"+                          , EApp (egName ["Server"] "shutdown") [ELName "server_"]+                          )                         , ( "handleCall"                           , ELambda [PVar "interfaceId_", PVar "methodId_"] $                                 ECase (euName "interfaceId_") $@@ -596,7 +607,12 @@ -- and those of its ancestors. ifaceServerInstances :: Word64 -> P.Interface -> [Decl] ifaceServerInstances thisMod iface@P.IFace{ name=Name.CapnpQ{local=name}, ancestors } =-    map go (iface:ancestors)+    DcInstance+        { ctx = []+        , typ = TApp (tgName ["Server"] "Server") [tStd_ "IO", TLName name]+        , defs = []+        }+    : map go (iface:ancestors)   where     go P.IFace { name=Name.CapnpQ{local, fileId}, interfaceId, methods } =         let className = Name.mkSub local "server_"
examples/gen/lib/Capnp/Gen/Calculator/Pure.hs view
@@ -59,7 +59,8 @@     deriving(Std_.Show             ,Std_.Eq             ,Generics.Generic)-class ((MonadIO.MonadIO m)) => (Calculator'server_ m cap) where+class ((MonadIO.MonadIO m)+      ,(Server.Server m cap)) => (Calculator'server_ m cap) where     {-# MINIMAL calculator'evaluate,calculator'defFunction,calculator'getOperator #-}     calculator'evaluate :: cap -> (Server.MethodHandler m Calculator'evaluate'params Calculator'evaluate'results)     calculator'evaluate _ = Server.methodUnimplemented@@ -69,7 +70,8 @@     calculator'getOperator _ = Server.methodUnimplemented export_Calculator :: ((Calculator'server_ Std_.IO a)                      ,(STM.MonadSTM m)) => Supervisors.Supervisor -> a -> (m Calculator)-export_Calculator sup_ server_ = (STM.liftSTM (Calculator <$> (Rpc.export sup_ Server.ServerOps{handleStop = (Std_.pure ())+export_Calculator sup_ server_ = (STM.liftSTM (Calculator <$> (Rpc.export sup_ Server.ServerOps{handleCast = (Server.unwrap server_)+                                                                                               ,handleStop = (Server.shutdown server_)                                                                                                ,handleCall = (\interfaceId_ methodId_ -> case interfaceId_ of                                                                                                    10923537602090224694 ->                                                                                                        case methodId_ of@@ -99,6 +101,7 @@             (Calculator <$> (Untyped.getClient cap)) instance (Classes.Cerialize Calculator) where     cerialize msg (Calculator client) = (Capnp.Gen.ById.X85150b117366d14b.Calculator'newtype_ <$> (Std_.Just <$> (Untyped.appendCap msg client)))+instance (Server.Server Std_.IO Calculator) instance (Calculator'server_ Std_.IO Calculator) where     calculator'evaluate (Calculator client) = (Rpc.clientMethodHandler 10923537602090224694 0 client)     calculator'defFunction (Calculator client) = (Rpc.clientMethodHandler 10923537602090224694 1 client)@@ -403,13 +406,15 @@     deriving(Std_.Show             ,Std_.Eq             ,Generics.Generic)-class ((MonadIO.MonadIO m)) => (Value'server_ m cap) where+class ((MonadIO.MonadIO m)+      ,(Server.Server m cap)) => (Value'server_ m cap) where     {-# MINIMAL value'read #-}     value'read :: cap -> (Server.MethodHandler m Value'read'params Value'read'results)     value'read _ = Server.methodUnimplemented export_Value :: ((Value'server_ Std_.IO a)                 ,(STM.MonadSTM m)) => Supervisors.Supervisor -> a -> (m Value)-export_Value sup_ server_ = (STM.liftSTM (Value <$> (Rpc.export sup_ Server.ServerOps{handleStop = (Std_.pure ())+export_Value sup_ server_ = (STM.liftSTM (Value <$> (Rpc.export sup_ Server.ServerOps{handleCast = (Server.unwrap server_)+                                                                                     ,handleStop = (Server.shutdown server_)                                                                                      ,handleCall = (\interfaceId_ methodId_ -> case interfaceId_ of                                                                                          14116142932258867410 ->                                                                                              case methodId_ of@@ -435,6 +440,7 @@             (Value <$> (Untyped.getClient cap)) instance (Classes.Cerialize Value) where     cerialize msg (Value client) = (Capnp.Gen.ById.X85150b117366d14b.Value'newtype_ <$> (Std_.Just <$> (Untyped.appendCap msg client)))+instance (Server.Server Std_.IO Value) instance (Value'server_ Std_.IO Value) where     value'read (Value client) = (Rpc.clientMethodHandler 14116142932258867410 0 client) data Value'read'params @@ -511,13 +517,15 @@     deriving(Std_.Show             ,Std_.Eq             ,Generics.Generic)-class ((MonadIO.MonadIO m)) => (Function'server_ m cap) where+class ((MonadIO.MonadIO m)+      ,(Server.Server m cap)) => (Function'server_ m cap) where     {-# MINIMAL function'call #-}     function'call :: cap -> (Server.MethodHandler m Function'call'params Function'call'results)     function'call _ = Server.methodUnimplemented export_Function :: ((Function'server_ Std_.IO a)                    ,(STM.MonadSTM m)) => Supervisors.Supervisor -> a -> (m Function)-export_Function sup_ server_ = (STM.liftSTM (Function <$> (Rpc.export sup_ Server.ServerOps{handleStop = (Std_.pure ())+export_Function sup_ server_ = (STM.liftSTM (Function <$> (Rpc.export sup_ Server.ServerOps{handleCast = (Server.unwrap server_)+                                                                                           ,handleStop = (Server.shutdown server_)                                                                                            ,handleCall = (\interfaceId_ methodId_ -> case interfaceId_ of                                                                                                17143016017778443156 ->                                                                                                    case methodId_ of@@ -543,6 +551,7 @@             (Function <$> (Untyped.getClient cap)) instance (Classes.Cerialize Function) where     cerialize msg (Function client) = (Capnp.Gen.ById.X85150b117366d14b.Function'newtype_ <$> (Std_.Just <$> (Untyped.appendCap msg client)))+instance (Server.Server Std_.IO Function) instance (Function'server_ Std_.IO Function) where     function'call (Function client) = (Rpc.clientMethodHandler 17143016017778443156 0 client) data Function'call'params 
examples/gen/lib/Capnp/Gen/Echo/Pure.hs view
@@ -42,13 +42,15 @@     deriving(Std_.Show             ,Std_.Eq             ,Generics.Generic)-class ((MonadIO.MonadIO m)) => (Echo'server_ m cap) where+class ((MonadIO.MonadIO m)+      ,(Server.Server m cap)) => (Echo'server_ m cap) where     {-# MINIMAL echo'echo #-}     echo'echo :: cap -> (Server.MethodHandler m Echo'echo'params Echo'echo'results)     echo'echo _ = Server.methodUnimplemented export_Echo :: ((Echo'server_ Std_.IO a)                ,(STM.MonadSTM m)) => Supervisors.Supervisor -> a -> (m Echo)-export_Echo sup_ server_ = (STM.liftSTM (Echo <$> (Rpc.export sup_ Server.ServerOps{handleStop = (Std_.pure ())+export_Echo sup_ server_ = (STM.liftSTM (Echo <$> (Rpc.export sup_ Server.ServerOps{handleCast = (Server.unwrap server_)+                                                                                   ,handleStop = (Server.shutdown server_)                                                                                    ,handleCall = (\interfaceId_ methodId_ -> case interfaceId_ of                                                                                        16940812395455687611 ->                                                                                            case methodId_ of@@ -74,6 +76,7 @@             (Echo <$> (Untyped.getClient cap)) instance (Classes.Cerialize Echo) where     cerialize msg (Echo client) = (Capnp.Gen.ById.Xd0a87f36fa0182f5.Echo'newtype_ <$> (Std_.Just <$> (Untyped.appendCap msg client)))+instance (Server.Server Std_.IO Echo) instance (Echo'server_ Std_.IO Echo) where     echo'echo (Echo client) = (Rpc.clientMethodHandler 16940812395455687611 0 client) data Echo'echo'params 
examples/lib/Examples/Rpc/CalculatorServer.hs view
@@ -19,6 +19,7 @@ import Capnp     (def, defaultLimit) import Capnp.Rpc     ( ConnConfig(..)+    , Server     , handleConn     , pureHandler     , socketTransport@@ -32,12 +33,16 @@  newtype LitValue = LitValue Double +instance Server IO LitValue+ instance Value'server_ IO LitValue where     value'read = pureHandler $ \(LitValue val) _ ->         pure Value'read'results { value = val }  newtype OpFunc = OpFunc (Double -> Double -> Double) +instance Server IO OpFunc+ instance Function'server_ IO OpFunc where     function'call = pureHandler $ \(OpFunc op) Function'call'params{params} -> do         when (V.length params /= 2) $@@ -50,6 +55,8 @@     , body       :: Expression     } +instance Server IO ExprFunc+ instance Function'server_ IO ExprFunc where     function'call =         pureHandler $ \ExprFunc{..} Function'call'params{params} -> do@@ -64,6 +71,8 @@     , divide   :: Function     , sup      :: Supervisor     }++instance Server IO MyCalc  instance Calculator'server_ IO MyCalc where     calculator'evaluate =
gen/lib/Capnp/Gen/Capnp/Persistent/Pure.hs view
@@ -47,13 +47,15 @@     deriving(Std_.Show             ,Std_.Eq             ,Generics.Generic)-class ((MonadIO.MonadIO m)) => (Persistent'server_ m cap) where+class ((MonadIO.MonadIO m)+      ,(Server.Server m cap)) => (Persistent'server_ m cap) where     {-# MINIMAL persistent'save #-}     persistent'save :: cap -> (Server.MethodHandler m Persistent'SaveParams Persistent'SaveResults)     persistent'save _ = Server.methodUnimplemented export_Persistent :: ((Persistent'server_ Std_.IO a)                      ,(STM.MonadSTM m)) => Supervisors.Supervisor -> a -> (m Persistent)-export_Persistent sup_ server_ = (STM.liftSTM (Persistent <$> (Rpc.export sup_ Server.ServerOps{handleStop = (Std_.pure ())+export_Persistent sup_ server_ = (STM.liftSTM (Persistent <$> (Rpc.export sup_ Server.ServerOps{handleCast = (Server.unwrap server_)+                                                                                               ,handleStop = (Server.shutdown server_)                                                                                                ,handleCall = (\interfaceId_ methodId_ -> case interfaceId_ of                                                                                                    14468694717054801553 ->                                                                                                        case methodId_ of@@ -79,6 +81,7 @@             (Persistent <$> (Untyped.getClient cap)) instance (Classes.Cerialize Persistent) where     cerialize msg (Persistent client) = (Capnp.Gen.ById.Xb8630836983feed7.Persistent'newtype_ <$> (Std_.Just <$> (Untyped.appendCap msg client)))+instance (Server.Server Std_.IO Persistent) instance (Persistent'server_ Std_.IO Persistent) where     persistent'save (Persistent client) = (Rpc.clientMethodHandler 14468694717054801553 0 client) data Persistent'SaveParams @@ -156,7 +159,8 @@     deriving(Std_.Show             ,Std_.Eq             ,Generics.Generic)-class ((MonadIO.MonadIO m)) => (RealmGateway'server_ m cap) where+class ((MonadIO.MonadIO m)+      ,(Server.Server m cap)) => (RealmGateway'server_ m cap) where     {-# MINIMAL realmGateway'import_,realmGateway'export #-}     realmGateway'import_ :: cap -> (Server.MethodHandler m RealmGateway'import'params Persistent'SaveResults)     realmGateway'import_ _ = Server.methodUnimplemented@@ -164,7 +168,8 @@     realmGateway'export _ = Server.methodUnimplemented export_RealmGateway :: ((RealmGateway'server_ Std_.IO a)                        ,(STM.MonadSTM m)) => Supervisors.Supervisor -> a -> (m RealmGateway)-export_RealmGateway sup_ server_ = (STM.liftSTM (RealmGateway <$> (Rpc.export sup_ Server.ServerOps{handleStop = (Std_.pure ())+export_RealmGateway sup_ server_ = (STM.liftSTM (RealmGateway <$> (Rpc.export sup_ Server.ServerOps{handleCast = (Server.unwrap server_)+                                                                                                   ,handleStop = (Server.shutdown server_)                                                                                                    ,handleCall = (\interfaceId_ methodId_ -> case interfaceId_ of                                                                                                        9583422979879616212 ->                                                                                                            case methodId_ of@@ -192,6 +197,7 @@             (RealmGateway <$> (Untyped.getClient cap)) instance (Classes.Cerialize RealmGateway) where     cerialize msg (RealmGateway client) = (Capnp.Gen.ById.Xb8630836983feed7.RealmGateway'newtype_ <$> (Std_.Just <$> (Untyped.appendCap msg client)))+instance (Server.Server Std_.IO RealmGateway) instance (RealmGateway'server_ Std_.IO RealmGateway) where     realmGateway'import_ (RealmGateway client) = (Rpc.clientMethodHandler 9583422979879616212 0 client)     realmGateway'export (RealmGateway client) = (Rpc.clientMethodHandler 9583422979879616212 1 client)
gen/tests/Capnp/Gen/Aircraft/Pure.hs view
@@ -1718,13 +1718,15 @@     deriving(Std_.Show             ,Std_.Eq             ,Generics.Generic)-class ((MonadIO.MonadIO m)) => (Echo'server_ m cap) where+class ((MonadIO.MonadIO m)+      ,(Server.Server m cap)) => (Echo'server_ m cap) where     {-# MINIMAL echo'echo #-}     echo'echo :: cap -> (Server.MethodHandler m Echo'echo'params Echo'echo'results)     echo'echo _ = Server.methodUnimplemented export_Echo :: ((Echo'server_ Std_.IO a)                ,(STM.MonadSTM m)) => Supervisors.Supervisor -> a -> (m Echo)-export_Echo sup_ server_ = (STM.liftSTM (Echo <$> (Rpc.export sup_ Server.ServerOps{handleStop = (Std_.pure ())+export_Echo sup_ server_ = (STM.liftSTM (Echo <$> (Rpc.export sup_ Server.ServerOps{handleCast = (Server.unwrap server_)+                                                                                   ,handleStop = (Server.shutdown server_)                                                                                    ,handleCall = (\interfaceId_ methodId_ -> case interfaceId_ of                                                                                        10255578992688506164 ->                                                                                            case methodId_ of@@ -1750,6 +1752,7 @@             (Echo <$> (Untyped.getClient cap)) instance (Classes.Cerialize Echo) where     cerialize msg (Echo client) = (Capnp.Gen.ById.X832bcc6686a26d56.Echo'newtype_ <$> (Std_.Just <$> (Untyped.appendCap msg client)))+instance (Server.Server Std_.IO Echo) instance (Echo'server_ Std_.IO Echo) where     echo'echo (Echo client) = (Rpc.clientMethodHandler 10255578992688506164 0 client) data Echo'echo'params @@ -2043,13 +2046,15 @@     deriving(Std_.Show             ,Std_.Eq             ,Generics.Generic)-class ((MonadIO.MonadIO m)) => (CallSequence'server_ m cap) where+class ((MonadIO.MonadIO m)+      ,(Server.Server m cap)) => (CallSequence'server_ m cap) where     {-# MINIMAL callSequence'getNumber #-}     callSequence'getNumber :: cap -> (Server.MethodHandler m CallSequence'getNumber'params CallSequence'getNumber'results)     callSequence'getNumber _ = Server.methodUnimplemented export_CallSequence :: ((CallSequence'server_ Std_.IO a)                        ,(STM.MonadSTM m)) => Supervisors.Supervisor -> a -> (m CallSequence)-export_CallSequence sup_ server_ = (STM.liftSTM (CallSequence <$> (Rpc.export sup_ Server.ServerOps{handleStop = (Std_.pure ())+export_CallSequence sup_ server_ = (STM.liftSTM (CallSequence <$> (Rpc.export sup_ Server.ServerOps{handleCast = (Server.unwrap server_)+                                                                                                   ,handleStop = (Server.shutdown server_)                                                                                                    ,handleCall = (\interfaceId_ methodId_ -> case interfaceId_ of                                                                                                        12371070827563042848 ->                                                                                                            case methodId_ of@@ -2075,6 +2080,7 @@             (CallSequence <$> (Untyped.getClient cap)) instance (Classes.Cerialize CallSequence) where     cerialize msg (CallSequence client) = (Capnp.Gen.ById.X832bcc6686a26d56.CallSequence'newtype_ <$> (Std_.Just <$> (Untyped.appendCap msg client)))+instance (Server.Server Std_.IO CallSequence) instance (CallSequence'server_ Std_.IO CallSequence) where     callSequence'getNumber (CallSequence client) = (Rpc.clientMethodHandler 12371070827563042848 0 client) data CallSequence'getNumber'params @@ -2151,13 +2157,15 @@     deriving(Std_.Show             ,Std_.Eq             ,Generics.Generic)-class ((MonadIO.MonadIO m)) => (CounterFactory'server_ m cap) where+class ((MonadIO.MonadIO m)+      ,(Server.Server m cap)) => (CounterFactory'server_ m cap) where     {-# MINIMAL counterFactory'newCounter #-}     counterFactory'newCounter :: cap -> (Server.MethodHandler m CounterFactory'newCounter'params CounterFactory'newCounter'results)     counterFactory'newCounter _ = Server.methodUnimplemented export_CounterFactory :: ((CounterFactory'server_ Std_.IO a)                          ,(STM.MonadSTM m)) => Supervisors.Supervisor -> a -> (m CounterFactory)-export_CounterFactory sup_ server_ = (STM.liftSTM (CounterFactory <$> (Rpc.export sup_ Server.ServerOps{handleStop = (Std_.pure ())+export_CounterFactory sup_ server_ = (STM.liftSTM (CounterFactory <$> (Rpc.export sup_ Server.ServerOps{handleCast = (Server.unwrap server_)+                                                                                                       ,handleStop = (Server.shutdown server_)                                                                                                        ,handleCall = (\interfaceId_ methodId_ -> case interfaceId_ of                                                                                                            15610220054254702620 ->                                                                                                                case methodId_ of@@ -2183,6 +2191,7 @@             (CounterFactory <$> (Untyped.getClient cap)) instance (Classes.Cerialize CounterFactory) where     cerialize msg (CounterFactory client) = (Capnp.Gen.ById.X832bcc6686a26d56.CounterFactory'newtype_ <$> (Std_.Just <$> (Untyped.appendCap msg client)))+instance (Server.Server Std_.IO CounterFactory) instance (CounterFactory'server_ Std_.IO CounterFactory) where     counterFactory'newCounter (CounterFactory client) = (Rpc.clientMethodHandler 15610220054254702620 0 client) data CounterFactory'newCounter'params @@ -2260,13 +2269,15 @@     deriving(Std_.Show             ,Std_.Eq             ,Generics.Generic)-class ((MonadIO.MonadIO m)) => (CounterAcceptor'server_ m cap) where+class ((MonadIO.MonadIO m)+      ,(Server.Server m cap)) => (CounterAcceptor'server_ m cap) where     {-# MINIMAL counterAcceptor'accept #-}     counterAcceptor'accept :: cap -> (Server.MethodHandler m CounterAcceptor'accept'params CounterAcceptor'accept'results)     counterAcceptor'accept _ = Server.methodUnimplemented export_CounterAcceptor :: ((CounterAcceptor'server_ Std_.IO a)                           ,(STM.MonadSTM m)) => Supervisors.Supervisor -> a -> (m CounterAcceptor)-export_CounterAcceptor sup_ server_ = (STM.liftSTM (CounterAcceptor <$> (Rpc.export sup_ Server.ServerOps{handleStop = (Std_.pure ())+export_CounterAcceptor sup_ server_ = (STM.liftSTM (CounterAcceptor <$> (Rpc.export sup_ Server.ServerOps{handleCast = (Server.unwrap server_)+                                                                                                         ,handleStop = (Server.shutdown server_)                                                                                                          ,handleCall = (\interfaceId_ methodId_ -> case interfaceId_ of                                                                                                              14317498215560924065 ->                                                                                                                  case methodId_ of@@ -2292,6 +2303,7 @@             (CounterAcceptor <$> (Untyped.getClient cap)) instance (Classes.Cerialize CounterAcceptor) where     cerialize msg (CounterAcceptor client) = (Capnp.Gen.ById.X832bcc6686a26d56.CounterAcceptor'newtype_ <$> (Std_.Just <$> (Untyped.appendCap msg client)))+instance (Server.Server Std_.IO CounterAcceptor) instance (CounterAcceptor'server_ Std_.IO CounterAcceptor) where     counterAcceptor'accept (CounterAcceptor client) = (Rpc.clientMethodHandler 14317498215560924065 0 client) data CounterAcceptor'accept'params @@ -2368,13 +2380,15 @@     deriving(Std_.Show             ,Std_.Eq             ,Generics.Generic)-class ((MonadIO.MonadIO m)) => (Top'server_ m cap) where+class ((MonadIO.MonadIO m)+      ,(Server.Server m cap)) => (Top'server_ m cap) where     {-# MINIMAL top'top #-}     top'top :: cap -> (Server.MethodHandler m Top'top'params Top'top'results)     top'top _ = Server.methodUnimplemented export_Top :: ((Top'server_ Std_.IO a)               ,(STM.MonadSTM m)) => Supervisors.Supervisor -> a -> (m Top)-export_Top sup_ server_ = (STM.liftSTM (Top <$> (Rpc.export sup_ Server.ServerOps{handleStop = (Std_.pure ())+export_Top sup_ server_ = (STM.liftSTM (Top <$> (Rpc.export sup_ Server.ServerOps{handleCast = (Server.unwrap server_)+                                                                                 ,handleStop = (Server.shutdown server_)                                                                                  ,handleCall = (\interfaceId_ methodId_ -> case interfaceId_ of                                                                                      17861645508359101525 ->                                                                                          case methodId_ of@@ -2400,6 +2414,7 @@             (Top <$> (Untyped.getClient cap)) instance (Classes.Cerialize Top) where     cerialize msg (Top client) = (Capnp.Gen.ById.X832bcc6686a26d56.Top'newtype_ <$> (Std_.Just <$> (Untyped.appendCap msg client)))+instance (Server.Server Std_.IO Top) instance (Top'server_ Std_.IO Top) where     top'top (Top client) = (Rpc.clientMethodHandler 17861645508359101525 0 client) data Top'top'params @@ -2482,7 +2497,8 @@     left'left _ = Server.methodUnimplemented export_Left :: ((Left'server_ Std_.IO a)                ,(STM.MonadSTM m)) => Supervisors.Supervisor -> a -> (m Left)-export_Left sup_ server_ = (STM.liftSTM (Left <$> (Rpc.export sup_ Server.ServerOps{handleStop = (Std_.pure ())+export_Left sup_ server_ = (STM.liftSTM (Left <$> (Rpc.export sup_ Server.ServerOps{handleCast = (Server.unwrap server_)+                                                                                   ,handleStop = (Server.shutdown server_)                                                                                    ,handleCall = (\interfaceId_ methodId_ -> case interfaceId_ of                                                                                        17679152961798450446 ->                                                                                            case methodId_ of@@ -2514,6 +2530,7 @@             (Left <$> (Untyped.getClient cap)) instance (Classes.Cerialize Left) where     cerialize msg (Left client) = (Capnp.Gen.ById.X832bcc6686a26d56.Left'newtype_ <$> (Std_.Just <$> (Untyped.appendCap msg client)))+instance (Server.Server Std_.IO Left) instance (Left'server_ Std_.IO Left) where     left'left (Left client) = (Rpc.clientMethodHandler 17679152961798450446 0 client) instance (Top'server_ Std_.IO Left) where@@ -2598,7 +2615,8 @@     right'right _ = Server.methodUnimplemented export_Right :: ((Right'server_ Std_.IO a)                 ,(STM.MonadSTM m)) => Supervisors.Supervisor -> a -> (m Right)-export_Right sup_ server_ = (STM.liftSTM (Right <$> (Rpc.export sup_ Server.ServerOps{handleStop = (Std_.pure ())+export_Right sup_ server_ = (STM.liftSTM (Right <$> (Rpc.export sup_ Server.ServerOps{handleCast = (Server.unwrap server_)+                                                                                     ,handleStop = (Server.shutdown server_)                                                                                      ,handleCall = (\interfaceId_ methodId_ -> case interfaceId_ of                                                                                          14712639595305348988 ->                                                                                              case methodId_ of@@ -2630,6 +2648,7 @@             (Right <$> (Untyped.getClient cap)) instance (Classes.Cerialize Right) where     cerialize msg (Right client) = (Capnp.Gen.ById.X832bcc6686a26d56.Right'newtype_ <$> (Std_.Just <$> (Untyped.appendCap msg client)))+instance (Server.Server Std_.IO Right) instance (Right'server_ Std_.IO Right) where     right'right (Right client) = (Rpc.clientMethodHandler 14712639595305348988 0 client) instance (Top'server_ Std_.IO Right) where@@ -2715,7 +2734,8 @@     bottom'bottom _ = Server.methodUnimplemented export_Bottom :: ((Bottom'server_ Std_.IO a)                  ,(STM.MonadSTM m)) => Supervisors.Supervisor -> a -> (m Bottom)-export_Bottom sup_ server_ = (STM.liftSTM (Bottom <$> (Rpc.export sup_ Server.ServerOps{handleStop = (Std_.pure ())+export_Bottom sup_ server_ = (STM.liftSTM (Bottom <$> (Rpc.export sup_ Server.ServerOps{handleCast = (Server.unwrap server_)+                                                                                       ,handleStop = (Server.shutdown server_)                                                                                        ,handleCall = (\interfaceId_ methodId_ -> case interfaceId_ of                                                                                            18402872613340521775 ->                                                                                                case methodId_ of@@ -2759,6 +2779,7 @@             (Bottom <$> (Untyped.getClient cap)) instance (Classes.Cerialize Bottom) where     cerialize msg (Bottom client) = (Capnp.Gen.ById.X832bcc6686a26d56.Bottom'newtype_ <$> (Std_.Just <$> (Untyped.appendCap msg client)))+instance (Server.Server Std_.IO Bottom) instance (Bottom'server_ Std_.IO Bottom) where     bottom'bottom (Bottom client) = (Rpc.clientMethodHandler 18402872613340521775 0 client) instance (Right'server_ Std_.IO Bottom) where
lib/Capnp/Rpc.hs view
@@ -13,6 +13,7 @@     , (?)      -- * Handling method calls+    , Server(..)     , MethodHandler     , pureHandler     , rawHandler@@ -36,6 +37,8 @@     , Client     , IsClient(..)     , newPromiseClient+    -- ** Reflection+    , Untyped.unwrapServer      -- * Supervisors     , module Supervisors@@ -50,6 +53,7 @@ import Capnp.Rpc.Promise import Capnp.Rpc.Server     ( MethodHandler+    , Server(..)     , methodThrow     , methodUnimplemented     , pureHandler@@ -60,3 +64,5 @@     (Transport(..), handleTransport, socketTransport, tracingTransport) import Capnp.Rpc.Untyped     (Client, ConnConfig(..), IsClient(..), handleConn, newPromiseClient)++import qualified Capnp.Rpc.Untyped as Untyped
lib/Capnp/Rpc/Server.hs view
@@ -1,9 +1,11 @@-{-# LANGUAGE FlexibleContexts    #-}-{-# LANGUAGE LambdaCase          #-}-{-# LANGUAGE NamedFieldPuns      #-}-{-# LANGUAGE RecordWildCards     #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies        #-}+{-# LANGUAGE FlexibleContexts       #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE LambdaCase             #-}+{-# LANGUAGE NamedFieldPuns         #-}+{-# LANGUAGE RankNTypes             #-}+{-# LANGUAGE RecordWildCards        #-}+{-# LANGUAGE ScopedTypeVariables    #-}+{-# LANGUAGE TypeFamilies           #-} {-| Module: Capnp.Rpc.Server Description: handlers for incoming method calls.@@ -13,7 +15,8 @@ clients and servers). -} module Capnp.Rpc.Server-    ( ServerOps(..)+    ( Server(..)+    , ServerOps(..)     , CallInfo(..)     , runServer @@ -43,6 +46,7 @@ import Control.Exception.Safe  (MonadCatch, finally, try) import Control.Monad.IO.Class  (MonadIO, liftIO) import Control.Monad.Primitive (PrimMonad, PrimState)+import Data.Typeable           (Typeable)  import Capnp.Classes     ( Cerialize@@ -206,6 +210,23 @@ methodUnimplemented :: MonadIO m => MethodHandler m p r methodUnimplemented = methodThrow eMethodUnimplemented +-- | Base class for things that can act as capnproto servers.+class Monad m => Server m a | a -> m where+    -- | Called when the last live reference to a server is dropped.+    shutdown :: a -> m ()+    shutdown _ = pure ()++    -- | Try to extract a value of a given type. The default implementation+    -- always fails (returns 'Nothing'). If an instance chooses to implement+    -- this, it will be possible to use "reflection" on clients that point+    -- at local servers to dynamically unwrap the server value. A typical+    -- implementation will just call Typeable's @cast@ method, but this+    -- needn't be the case -- a server may wish to allow local peers to+    -- unwrap some value that is not exactly the data the server has access+    -- to.+    unwrap :: Typeable b => a -> Maybe b+    unwrap _ = Nothing+ -- | The operations necessary to receive and handle method calls, i.e. -- to implement an object. It is parametrized over the monadic context -- in which methods are serviced.@@ -219,6 +240,8 @@     , handleStop :: m ()     -- ^ Handle shutting-down the receiver; this is called when the last     -- reference to the capability is dropped.+    , handleCast :: forall a. Typeable a => Maybe a+    -- ^ used to unwrap the server when reflecting on a local client.     }  -- | A 'CallInfo' contains information about a method call.
lib/Capnp/Rpc/Untyped.hs view
@@ -5,6 +5,7 @@ {-# LANGUAGE LambdaCase                 #-} {-# LANGUAGE NamedFieldPuns             #-} {-# LANGUAGE OverloadedStrings          #-}+{-# LANGUAGE RankNTypes                 #-} {-# LANGUAGE RecordWildCards            #-} {-# LANGUAGE RecursiveDo                #-} {-# LANGUAGE ScopedTypeVariables        #-}@@ -34,6 +35,9 @@     , export     , clientMethodHandler +    -- * Unwrapping local clients+    , unwrapServer+     -- * Errors     , RpcError(..)     , R.Exception(..)@@ -57,6 +61,7 @@ import Data.Maybe               (catMaybes) import Data.String              (fromString) import Data.Text                (Text)+import Data.Typeable            (Typeable) import GHC.Generics             (Generic) import Supervisors              (Supervisor, superviseSTM, withSupervisor) import System.Mem.StableName    (StableName, hashStableName, makeStableName)@@ -567,6 +572,7 @@         -- in a reference counted cell, whose finalizer stops the server.         , finalizerKey :: Fin.Cell ()         -- ^ Finalizer key; when this is collected, qCall will be released.+        , unwrapper    :: forall a. Typeable a => Maybe a         }     -- | A client which will resolve to some other capability at     -- some point.@@ -862,8 +868,8 @@     pState <- newTVar Pending { tmpDest }     exportMap <- ExportMap <$> M.new     f <- newCallback $ \case-        Left e -> writeTVar pState (Error e)-        Right v -> writeTVar pState Ready { target = toClient v }+        Left e -> resolveClientExn tmpDest (writeTVar pState) e+        Right v -> resolveClientClient tmpDest (writeTVar pState) (toClient v)     let p = Client $ Just $ PromiseClient             { pState             , exportMap@@ -872,6 +878,21 @@     pure (fromClient p, f)  +-- | Attempt to unwrap a client, to get at an underlying value from the+-- server. Returns 'Nothing' on failure.+--+-- This shells out to the underlying server's implementation of+-- 'Server.unwrap'. It will fail with 'Nothing' if any of these are true:+--+-- * The client is a promise.+-- * The client points to an object in a remote vat.+-- * The underlying Server's 'unwrap' method returns 'Nothing' for type 'a'.+unwrapServer :: (IsClient c, Typeable a) => c -> Maybe a+unwrapServer c = case toClient c of+    Client (Just LocalClient { unwrapper }) -> unwrapper+    _                                       -> Nothing++ -- | Spawn a local server with its lifetime bound to the supervisor, -- and return a client for it. When the client is garbage collected, -- the server will be stopped (if it is still running).@@ -885,6 +906,7 @@             { qCall             , exportMap             , finalizerKey+            , unwrapper = Server.handleCast ops             }     superviseSTM sup $ do         Fin.addFinalizer finalizerKey $ atomically $ Rc.release qCall
tests/Main.hs view
@@ -11,6 +11,7 @@ import Module.Capnp.Untyped               (untypedTests) import Module.Capnp.Untyped.Pure          (pureUntypedTests) import Regression                         (regressionTests)+import Rpc.Unwrap                         (unwrapTests) import SchemaQuickCheck                   (schemaCGRQuickCheck) import WalkSchemaCodeGenRequest           (walkSchemaCodeGenRequestTest) @@ -33,3 +34,4 @@         describe "property tests for schema" schemaCGRQuickCheck     describe "Regression tests" regressionTests     CalculatorExample.tests+    describe "Tests for client unwrapping" unwrapTests
tests/Module/Capnp/Rpc.hs view
@@ -22,6 +22,7 @@ import qualified Data.ByteString.Builder as BB import qualified Data.Text               as T import qualified Network.Socket          as Socket+import qualified Supervisors  import Capnp     ( createPure@@ -71,6 +72,7 @@  data TestEchoServer = TestEchoServer +instance Server IO TestEchoServer instance E.Echo'server_ IO TestEchoServer where     echo'echo = pureHandler $ \_ params -> pure def { E.reply = E.query params } @@ -82,10 +84,32 @@  -- | Bump a counter n times, returning a list of the results. bumpN :: CallSequence -> Int -> IO [CallSequence'getNumber'results]-bumpN ctr n = replicateM n (callSequence'getNumber ctr ? def) >>= traverse wait+bumpN ctr n = bumpNPromise ctr n >>= traverse wait +-- | Like 'bumpN', but doesn't wait for the results -- returns a list of promises.+bumpNPromise :: CallSequence -> Int -> IO [Promise CallSequence'getNumber'results]+bumpNPromise ctr n = replicateM n (callSequence'getNumber ctr ? def)+ aircraftTests :: Spec aircraftTests = describe "aircraft.capnp rpc tests" $ do+    describe "newPromiseClient" $+        it "Should preserve E-order" $+            Supervisors.withSupervisor $ \sup -> do+                (pc, f) <- newPromiseClient+                firsts <- bumpNPromise pc 2+                atomically (newTestCtr 0)+                    >>= export_CallSequence sup+                    >>= fulfill f+                nexts <- bumpN pc 2+                firstsResolved <- traverse wait firsts+                firstsResolved `shouldBe`+                    [ def { n = 1 }+                    , def { n = 2 }+                    ]+                nexts `shouldBe`+                    [ def { n = 3 }+                    , def { n = 4 }+                    ]     it "Should propogate server-side exceptions to client method calls" $ runVatPair         (`export_CallSequence` ExnCtrServer)         (\_sup -> expectException@@ -125,8 +149,7 @@     it "A counter should maintain state" $ runVatPair         (\sup -> newTestCtr 0 >>= export_CallSequence sup)         (\_sup ctr -> do-            results <- replicateM 4 (callSequence'getNumber ctr ? def)-                >>= traverse wait+            results <- bumpN ctr 4             liftIO $ results `shouldBe`                 [ def { n = 1 }                 , def { n = 2 }@@ -191,6 +214,7 @@  data TestCtrAcceptor = TestCtrAcceptor +instance Server IO TestCtrAcceptor instance CounterAcceptor'server_ IO TestCtrAcceptor where     counterAcceptor'accept =         pureHandler $ \_ CounterAcceptor'accept'params{counter} -> do@@ -210,6 +234,7 @@  newtype TestCtrFactory = TestCtrFactory { sup :: Supervisor } +instance Server IO TestCtrFactory instance CounterFactory'server_ IO TestCtrFactory where     counterFactory'newCounter =         pureHandler $ \TestCtrFactory{sup} CounterFactory'newCounter'params{start} -> do@@ -221,6 +246,7 @@  newtype TestCtrServer = TestCtrServer (TVar Word32) +instance Server IO TestCtrServer instance CallSequence'server_ IO TestCtrServer  where     callSequence'getNumber = pureHandler $ \(TestCtrServer tvar) _ -> do         ret <- liftIO $ atomically $ do@@ -231,6 +257,7 @@ -- a 'CallSequence' which always throws an exception. data ExnCtrServer = ExnCtrServer +instance Server IO ExnCtrServer instance CallSequence'server_ IO ExnCtrServer where     callSequence'getNumber = pureHandler $ \_ _ ->         throwM def@@ -241,11 +268,13 @@ -- a 'CallSequence' which doesn't implement its methods. data NoImplServer = NoImplServer +instance Server IO NoImplServer instance CallSequence'server_ IO NoImplServer -- TODO: can we silence the warning somehow?  -- Server that throws some non-rpc exception. data NonRpcExnServer = NonRpcExnServer +instance Server IO NonRpcExnServer instance CallSequence'server_ IO NonRpcExnServer where     callSequence'getNumber = pureHandler $ \_ _ -> error "OOPS" @@ -253,7 +282,7 @@ -- Tests for unusual patterns of messages . -- -- Some of these will never come up when talking to a correct implementation of--- capnproto, and others just won't come up when talking to Haskell+-- capnproto, and others just won't come up when talking to the Haskell -- implementation. Accordingly, these tests start a vat in one thread and -- directly manipulate the transport in the other. -------------------------------------------------------------------------------
+ tests/Rpc/Unwrap.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables   #-}+module Rpc.Unwrap (unwrapTests) where++import Test.Hspec++import qualified Data.Typeable as Typeable++import Data.Typeable (Typeable)++import qualified Capnp.Gen.Aircraft.Pure as Aircraft+import qualified Capnp.Rpc               as Rpc+import qualified Supervisors++data OpaqueEcho = OpaqueEcho+    deriving(Show, Read, Eq, Ord, Enum, Bounded)++instance Rpc.Server IO OpaqueEcho++instance Aircraft.Echo'server_ IO OpaqueEcho where+    echo'echo _ = Rpc.methodUnimplemented++newtype TransparentEcho = TransparentEcho Int+    deriving(Show, Read, Eq, Ord, Bounded, Typeable)++instance Rpc.Server IO TransparentEcho where+    unwrap = Typeable.cast++instance Aircraft.Echo'server_ IO TransparentEcho where+    echo'echo _ = Rpc.methodUnimplemented+++unwrapTests :: Spec+unwrapTests = describe "Tests for client unwrapping" $ do+    it "Should return nothing for OpaqueEcho." $ do+        r :: Maybe OpaqueEcho <- exportAndUnwrap OpaqueEcho+        r `shouldBe` Nothing+    it "Should return nothing for the wrong type." $ do+        r :: Maybe () <- exportAndUnwrap (TransparentEcho 4)+        r `shouldBe` Nothing+    it "Should return the value for TransparentEcho." $ do+        r <- exportAndUnwrap (TransparentEcho 4)+        r `shouldBe` Just (TransparentEcho 4)++exportAndUnwrap :: (Aircraft.Echo'server_ IO a, Typeable b) => a -> IO (Maybe b)+exportAndUnwrap srv = Supervisors.withSupervisor $ \sup -> do+    client <- Aircraft.export_Echo sup srv+    pure $ Rpc.unwrapServer client