{-# Language TemplateHaskell #-} {-# Language UndecidableInstances #-} module RPC where import HBS2.Prelude.Plated import HBS2.Net.Proto import HBS2.Hash import HBS2.Net.Messaging.UDP import HBS2.Actors.Peer import HBS2.Net.Auth.Credentials import HBS2.Net.Proto.Definition() import PeerConfig import Data.Text (Text) import Control.Monad.Reader import Data.ByteString.Lazy (ByteString) import Codec.Serialise (serialise,deserialiseOrFail) import Lens.Micro.Platform data SetLogging = DebugOn Bool | TraceOn Bool deriving (Generic,Eq,Show) instance Serialise SetLogging data RPC e = RPCPoke | RPCPing (PeerAddr e) | RPCPong (PeerAddr e) | RPCPokeAnswer (PubKey 'Sign e) | RPCPokeAnswerFull Text | RPCAnnounce (Hash HbSync) | RPCFetch (Hash HbSync) | RPCPeers | RPCPeersAnswer (PeerAddr e) (PubKey 'Sign e) | RPCLogLevel SetLogging | RPCRefLogUpdate ByteString | RPCRefLogFetch (PubKey 'Sign e) | RPCRefLogGet (PubKey 'Sign e) | RPCRefLogGetAnswer (Maybe (Hash HbSync)) deriving stock (Generic) instance Serialise (PeerAddr e) => Serialise (RPC e) instance HasProtocol UDP (RPC UDP) where type instance ProtocolId (RPC UDP) = 0xFFFFFFE0 type instance Encoded UDP = ByteString decode = either (const Nothing) Just . deserialiseOrFail encode = serialise data RPCEnv = RPCEnv { _rpcSelf :: Peer UDP , _rpcFab :: Fabriq UDP } makeLenses 'RPCEnv data RpcAdapter e m = RpcAdapter { rpcOnPoke :: RPC e -> m () , rpcOnPokeAnswer :: PubKey 'Sign e -> m () , rpcOnPokeAnswerFull :: Text -> m () , rpcOnAnnounce :: Hash HbSync -> m () , rpcOnPing :: PeerAddr e -> m () , rpcOnPong :: PeerAddr e -> m () , rpcOnFetch :: Hash HbSync -> m () , rpcOnPeers :: RPC e -> m () , rpcOnPeersAnswer :: (PeerAddr e, PubKey 'Sign e) -> m () , rpcOnLogLevel :: SetLogging -> m () , rpcOnRefLogUpdate :: ByteString -> m () , rpcOnRefLogFetch :: PubKey 'Sign e -> m () , rpcOnRefLogGet :: PubKey 'Sign e -> m () , rpcOnRefLogGetAnsw :: Maybe (Hash HbSync) -> m () } newtype RpcM m a = RpcM { fromRpcM :: ReaderT RPCEnv m a } deriving newtype ( Functor , Applicative , Monad , MonadIO , MonadReader RPCEnv , MonadTrans ) runRPC :: ( MonadIO m , PeerMessaging UDP ) => MessagingUDP -> RpcM m a -> m a runRPC udp m = runReaderT (fromRpcM m) (RPCEnv pip (Fabriq udp)) where pip = getOwnPeer udp continueWithRPC :: RPCEnv -> RpcM m a -> m a continueWithRPC e m = runReaderT (fromRpcM m) e instance Monad m => HasFabriq UDP (RpcM m) where getFabriq = asks (view rpcFab) instance Monad m => HasOwnPeer UDP (RpcM m) where ownPeer = asks (view rpcSelf) instance (Monad m, HasProtocol UDP p) => HasTimeLimits UDP p (RpcM m) where tryLockForPeriod _ _ = pure True rpcHandler :: forall e m . ( MonadIO m , Response e (RPC e) m , HasProtocol e (RPC e) , IsPeerAddr e m ) => RpcAdapter e m -> RPC e -> m () rpcHandler adapter = \case p@RPCPoke{} -> rpcOnPoke adapter p (RPCPokeAnswer k) -> rpcOnPokeAnswer adapter k (RPCPokeAnswerFull k) -> rpcOnPokeAnswerFull adapter k (RPCAnnounce h) -> rpcOnAnnounce adapter h (RPCPing pa) -> rpcOnPing adapter pa (RPCPong pa) -> rpcOnPong adapter pa (RPCFetch h) -> rpcOnFetch adapter h p@RPCPeers{} -> rpcOnPeers adapter p (RPCPeersAnswer pa k) -> rpcOnPeersAnswer adapter (pa,k) (RPCLogLevel l) -> rpcOnLogLevel adapter l (RPCRefLogUpdate bs) -> rpcOnRefLogUpdate adapter bs (RPCRefLogFetch e) -> rpcOnRefLogFetch adapter e (RPCRefLogGet e) -> rpcOnRefLogGet adapter e (RPCRefLogGetAnswer s) -> rpcOnRefLogGetAnsw adapter s