This commit is contained in:
voidlizard 2024-10-11 12:31:04 +03:00
parent 77401978fd
commit 6962b7412e
7 changed files with 114 additions and 24 deletions

View File

@ -137,6 +137,19 @@ runMailboxCLI rpc s = do
_ -> throwIO $ BadFormException @C nil _ -> throwIO $ BadFormException @C nil
brief "get mailbox status"
$ entry $ bindMatch "status" $ nil_ $ \case
[ SignPubKeyLike m ] -> do
v <- callRpcWaitMay @RpcMailboxGetStatus t api m
>>= orThrowUser "rpc call timeout"
>>= orThrowPassIO
liftIO $ print $ pretty v
_ -> throwIO $ BadFormException @C nil
brief "list mailboxes" brief "list mailboxes"
$ entry $ bindMatch "list" $ nil_ $ const do $ entry $ bindMatch "list" $ nil_ $ const do

View File

@ -37,18 +37,19 @@ import BlockDownload()
import DBPipe.SQLite import DBPipe.SQLite
import Control.Monad.Trans.Cont
import Control.Monad.Trans.Maybe
import Data.Maybe
import UnliftIO
import Control.Concurrent.STM qualified as STM import Control.Concurrent.STM qualified as STM
-- import Control.Concurrent.STM.TBQueue -- import Control.Concurrent.STM.TBQueue
import Data.HashMap.Strict qualified as HM import Control.Monad.Trans.Cont
import Control.Monad.Trans.Maybe
import Data.Coerce
import Data.HashMap.Strict (HashMap) import Data.HashMap.Strict (HashMap)
import Data.HashSet qualified as HS import Data.HashMap.Strict qualified as HM
import Data.HashSet (HashSet) import Data.HashSet (HashSet)
import Data.HashSet qualified as HS
import Data.Maybe
import Lens.Micro.Platform import Lens.Micro.Platform
import Text.InterpolatedString.Perl6 (qc) import Text.InterpolatedString.Perl6 (qc)
import UnliftIO
data MailboxProtoException = data MailboxProtoException =
MailboxProtoWorkerTerminatedException MailboxProtoWorkerTerminatedException
@ -68,6 +69,7 @@ data MailboxProtoWorker (s :: CryptoScheme) e =
{ mpwPeerEnv :: PeerEnv e { mpwPeerEnv :: PeerEnv e
, mpwDownloadEnv :: DownloadEnv e , mpwDownloadEnv :: DownloadEnv e
, mpwStorage :: AnyStorage , mpwStorage :: AnyStorage
, mpwCredentials :: PeerCredentials s
, inMessageQueue :: TBQueue (Message s, MessageContent s) , inMessageQueue :: TBQueue (Message s, MessageContent s)
, inMessageMergeQueue :: TVar (HashMap (MailboxRefKey s) (HashSet HashRef)) , inMessageMergeQueue :: TVar (HashMap (MailboxRefKey s) (HashSet HashRef))
, inMessageQueueInNum :: TVar Int , inMessageQueueInNum :: TVar Int
@ -78,6 +80,9 @@ data MailboxProtoWorker (s :: CryptoScheme) e =
} }
instance (s ~ HBS2Basic, e ~ L4Proto, s ~ Encryption e) => IsMailboxProtoAdapter s (MailboxProtoWorker s e) where instance (s ~ HBS2Basic, e ~ L4Proto, s ~ Encryption e) => IsMailboxProtoAdapter s (MailboxProtoWorker s e) where
mailboxGetCredentials = pure . mpwCredentials
mailboxGetStorage = pure . mpwStorage mailboxGetStorage = pure . mpwStorage
mailboxAcceptMessage MailboxProtoWorker{..} m c = do mailboxAcceptMessage MailboxProtoWorker{..} m c = do
@ -159,22 +164,39 @@ instance ( s ~ Encryption e, e ~ L4Proto
pure $ Right r pure $ Right r
mailboxGetStatus MailboxProtoWorker{..} ref = do mailboxGetStatus MailboxProtoWorker{..} ref = do
undefined -- TODO: support-policy-ASAP
getMailboxType_ :: (ForMailbox s, MonadIO m) => DBPipeEnv -> Recipient s -> m (Maybe MailboxType) now <- liftIO $ getPOSIXTime <&> round
flip runContT pure do
mdbe <- readTVarIO mailboxDB
dbe <- ContT $ maybe1 mdbe (pure $ Left (MailboxCreateFailed "database not ready"))
t' <- getMailboxType_ dbe ref
t <- ContT $ maybe1 t' (pure $ Right Nothing)
v <- getRef mpwStorage ref <&> fmap HashRef
pure $ Right $ Just $ MailBoxStatusPayload @s now (coerce ref) t v mzero mzero
getMailboxType_ :: (ForMailbox s, MonadIO m) => DBPipeEnv -> MailboxRefKey s -> m (Maybe MailboxType)
getMailboxType_ d r = do getMailboxType_ d r = do
let sql = [qc|select type from mailbox where recipient = ? limit 1|] let sql = [qc|select type from mailbox where recipient = ? limit 1|]
withDB d do withDB d do
select @(Only String) sql (Only (show $ pretty (AsBase58 r))) select @(Only String) sql (Only r)
<&> fmap (fromStringMay @MailboxType . fromOnly) <&> fmap (fromStringMay @MailboxType . fromOnly)
<&> headMay . catMaybes <&> headMay . catMaybes
createMailboxProtoWorker :: forall s e m . (MonadIO m, s ~ Encryption e, ForMailbox s) createMailboxProtoWorker :: forall s e m . (MonadIO m, s ~ Encryption e, ForMailbox s)
=> PeerEnv e => PeerCredentials s
-> PeerEnv e
-> DownloadEnv e -> DownloadEnv e
-> AnyStorage -> AnyStorage
-> m (MailboxProtoWorker s e) -> m (MailboxProtoWorker s e)
createMailboxProtoWorker pe de sto = do createMailboxProtoWorker pc pe de sto = do
-- FIXME: queue-size-hardcode -- FIXME: queue-size-hardcode
-- $class: hardcode -- $class: hardcode
inQ <- newTBQueueIO 1000 inQ <- newTBQueueIO 1000
@ -184,7 +206,7 @@ createMailboxProtoWorker pe de sto = do
outNum <- newTVarIO 0 outNum <- newTVarIO 0
decl <- newTVarIO 0 decl <- newTVarIO 0
dbe <- newTVarIO Nothing dbe <- newTVarIO Nothing
pure $ MailboxProtoWorker pe de sto inQ mergeQ inNum outNum inDroppped decl dbe pure $ MailboxProtoWorker pe de sto pc inQ mergeQ inNum outNum inDroppped decl dbe
mailboxProtoWorker :: forall e s m . ( MonadIO m mailboxProtoWorker :: forall e s m . ( MonadIO m
, MonadUnliftIO m , MonadUnliftIO m
@ -243,7 +265,7 @@ mailboxProtoWorker readConf me@MailboxProtoWorker{..} = do
-- TODO: process-with-policy -- TODO: process-with-policy
for_ (messageRecipients s) $ \rcpt -> void $ runMaybeT do for_ (messageRecipients s) $ \rcpt -> void $ runMaybeT do
mbox <- getMailboxType_ @s dbe rcpt mbox <- getMailboxType_ @s dbe (MailboxRefKey rcpt)
>>= toMPlus >>= toMPlus
-- TODO: ASAP-block-accounting -- TODO: ASAP-block-accounting

View File

@ -902,7 +902,7 @@ runPeer opts = Exception.handle (\e -> myException e
rcw <- async $ liftIO $ runRefChanRelyWorker rce refChanAdapter rcw <- async $ liftIO $ runRefChanRelyWorker rce refChanAdapter
mailboxWorker <- createMailboxProtoWorker penv denv (AnyStorage s) mailboxWorker <- createMailboxProtoWorker pc penv denv (AnyStorage s)
let onNoBlock (p, h) = do let onNoBlock (p, h) = do
already <- liftIO $ Cache.lookup nbcache (p,h) <&> isJust already <- liftIO $ Cache.lookup nbcache (p,h) <&> isJust

View File

@ -11,6 +11,8 @@ import HBS2.Data.Types.SignedBox
import HBS2.Peer.Proto import HBS2.Peer.Proto
import HBS2.Peer.Proto.Mailbox import HBS2.Peer.Proto.Mailbox
import HBS2.Peer.Proto.Mailbox.Ref import HBS2.Peer.Proto.Mailbox.Ref
import HBS2.Peer.Proto.Mailbox.Types
import HBS2.Storage import HBS2.Storage
import HBS2.Net.Messaging.Unix import HBS2.Net.Messaging.Unix
import HBS2.Misc.PrettyStuff import HBS2.Misc.PrettyStuff
@ -45,6 +47,14 @@ instance (ForMailboxRPC m) => HandleMethod m RpcMailboxCreate where
void $ mailboxCreate @HBS2Basic mbs t puk void $ mailboxCreate @HBS2Basic mbs t puk
debug $ "rpc.RpcMailboxCreate" <+> pretty (AsBase58 puk) <+> pretty t debug $ "rpc.RpcMailboxCreate" <+> pretty (AsBase58 puk) <+> pretty t
instance (ForMailboxRPC m) => HandleMethod m RpcMailboxGetStatus where
handleMethod puk = do
AnyMailboxService mbs <- getRpcContext @MailboxAPI @RPC2Context <&> rpcMailboxService
debug $ "rpc.RpcMailboxGetStatus" <+> pretty (AsBase58 puk)
mailboxGetStatus @HBS2Basic mbs (MailboxRefKey puk)
instance (ForMailboxRPC m) => HandleMethod m RpcMailboxDelete where instance (ForMailboxRPC m) => HandleMethod m RpcMailboxDelete where
handleMethod puk = do handleMethod puk = do

View File

@ -10,23 +10,29 @@ module HBS2.Peer.Proto.Mailbox
import HBS2.Prelude.Plated import HBS2.Prelude.Plated
import HBS2.Hash import HBS2.Hash
import HBS2.Base58
import HBS2.Data.Types.Refs import HBS2.Data.Types.Refs
import HBS2.Data.Types.SignedBox import HBS2.Data.Types.SignedBox
import HBS2.Storage import HBS2.Storage
import HBS2.Actors.Peer.Types import HBS2.Actors.Peer.Types
import HBS2.Net.Auth.Credentials
import HBS2.Peer.Proto.Mailbox.Types import HBS2.Peer.Proto.Mailbox.Types
import HBS2.Peer.Proto.Mailbox.Message import HBS2.Peer.Proto.Mailbox.Message
import HBS2.Peer.Proto.Mailbox.Entry import HBS2.Peer.Proto.Mailbox.Entry
import HBS2.Peer.Proto.Mailbox.Ref import HBS2.Peer.Proto.Mailbox.Ref
import Data.Maybe
import Control.Monad.Trans.Cont
import Codec.Serialise() import Codec.Serialise()
import Control.Monad.Trans.Cont
import Control.Monad.Trans.Maybe
import Data.Maybe
import Data.Word
import Lens.Micro.Platform
data MailBoxStatusPayload s = data MailBoxStatusPayload s =
MailBoxStatusPayload MailBoxStatusPayload
{ mbsMailboxKey :: MailboxKey s { mbsMailboxPayloadNonce :: Word64
, mbsMailboxKey :: MailboxKey s
, mbsMailboxType :: MailboxType , mbsMailboxType :: MailboxType
, mbsMailboxHash :: Maybe HashRef , mbsMailboxHash :: Maybe HashRef
, mbsMailboxPolicyVersion :: Maybe PolicyVersion , mbsMailboxPolicyVersion :: Maybe PolicyVersion
@ -69,6 +75,8 @@ instance ForMailbox s => Serialise (MailBoxProto s e)
class IsMailboxProtoAdapter s a where class IsMailboxProtoAdapter s a where
mailboxGetCredentials :: forall m . MonadIO m => a -> m (PeerCredentials s)
mailboxGetStorage :: forall m . MonadIO m => a -> m AnyStorage mailboxGetStorage :: forall m . MonadIO m => a -> m AnyStorage
mailboxAcceptMessage :: forall m . (ForMailbox s, MonadIO m) mailboxAcceptMessage :: forall m . (ForMailbox s, MonadIO m)
@ -77,10 +85,6 @@ class IsMailboxProtoAdapter s a where
-> MessageContent s -> MessageContent s
-> m () -> m ()
data MailboxServiceError =
MailboxCreateFailed String
deriving stock (Typeable,Show)
class ForMailbox s => IsMailboxService s a where class ForMailbox s => IsMailboxService s a where
@ -132,9 +136,26 @@ instance ForMailbox s => IsMailboxService s (AnyMailboxService s) where
mailboxGetStatus (AnyMailboxService a) = mailboxGetStatus @s a mailboxGetStatus (AnyMailboxService a) = mailboxGetStatus @s a
instance IsMailboxProtoAdapter s (AnyMailboxAdapter s) where instance IsMailboxProtoAdapter s (AnyMailboxAdapter s) where
mailboxGetCredentials (AnyMailboxAdapter a) = mailboxGetCredentials @s a
mailboxGetStorage (AnyMailboxAdapter a) = mailboxGetStorage @s a mailboxGetStorage (AnyMailboxAdapter a) = mailboxGetStorage @s a
mailboxAcceptMessage (AnyMailboxAdapter a) = mailboxAcceptMessage @s a mailboxAcceptMessage (AnyMailboxAdapter a) = mailboxAcceptMessage @s a
instance ForMailbox s => Pretty (MailBoxStatusPayload s) where
pretty MailBoxStatusPayload{..} =
parens $ "mailbox-status" <> line <> st
where
st = indent 2 $
brackets $
vcat [ parens ("nonce" <+> pretty mbsMailboxPayloadNonce)
, parens ("key" <+> pretty (AsBase58 mbsMailboxKey))
, parens ("type" <+> pretty mbsMailboxType)
, element "mailbox-tree" mbsMailboxHash
, element "policy-version" mbsMailboxPolicyVersion
, element "policy-tree" mbsMailboxPolicyHash
]
element el = maybe mempty ( \v -> parens (el <+> pretty v) )
mailboxProto :: forall e s m p a . ( MonadIO m mailboxProto :: forall e s m p a . ( MonadIO m
, Response e p m , Response e p m
, HasDeferred p e m , HasDeferred p e m
@ -228,10 +249,20 @@ mailboxProto inner adapter mess = deferred @p do
-- и так и известен в протоколе) -- и так и известен в протоколе)
-- --
CheckMailbox k -> do CheckMailbox k -> deferred @p do
creds <- mailboxGetCredentials @s adapter
void $ runMaybeT do
-- TODO: check-policy -- TODO: check-policy
none s <- mailboxGetStatus adapter (MailboxRefKey @s k)
>>= toMPlus
>>= toMPlus
let box = makeSignedBox @s (view peerSignPk creds) (view peerSignSk creds) s
lift $ response @_ @p (MailBoxProtoV1 (MailboxStatus box))
MailboxStatus{} -> do MailboxStatus{} -> do
-- TODO: implement-MailboxStatus -- TODO: implement-MailboxStatus
@ -253,4 +284,3 @@ mailboxProto inner adapter mess = deferred @p do
none none

View File

@ -4,6 +4,7 @@ module HBS2.Peer.Proto.Mailbox.Types
( ForMailbox ( ForMailbox
, MailboxKey , MailboxKey
, MailboxType(..) , MailboxType(..)
, MailboxServiceError(..)
, Recipient , Recipient
, Sender , Sender
, PolicyVersion , PolicyVersion
@ -26,6 +27,14 @@ import HBS2.Net.Auth.GroupKeySymm
import Data.Word (Word32) import Data.Word (Word32)
import Codec.Serialise import Codec.Serialise
import Data.Maybe import Data.Maybe
import Control.Exception
data MailboxServiceError =
MailboxCreateFailed String
deriving stock (Typeable,Show,Generic)
instance Serialise MailboxServiceError
instance Exception MailboxServiceError
data MailboxType = data MailboxType =
MailboxHub | MailboxRelay MailboxHub | MailboxRelay

View File

@ -17,6 +17,7 @@ import Codec.Serialise
data RpcMailboxPoke data RpcMailboxPoke
data RpcMailboxCreate data RpcMailboxCreate
data RpcMailboxDelete data RpcMailboxDelete
data RpcMailboxGetStatus
data RpcMailboxList data RpcMailboxList
data RpcMailboxSend data RpcMailboxSend
data RpcMailboxGet data RpcMailboxGet
@ -24,6 +25,7 @@ data RpcMailboxGet
type MailboxAPI = '[ RpcMailboxPoke type MailboxAPI = '[ RpcMailboxPoke
, RpcMailboxCreate , RpcMailboxCreate
, RpcMailboxDelete , RpcMailboxDelete
, RpcMailboxGetStatus
, RpcMailboxList , RpcMailboxList
, RpcMailboxSend , RpcMailboxSend
, RpcMailboxGet , RpcMailboxGet
@ -47,6 +49,10 @@ type instance Output RpcMailboxCreate = ()
type instance Input RpcMailboxDelete = (PubKey 'Sign HBS2Basic) type instance Input RpcMailboxDelete = (PubKey 'Sign HBS2Basic)
type instance Output RpcMailboxDelete = () type instance Output RpcMailboxDelete = ()
type instance Input RpcMailboxGetStatus = (PubKey 'Sign HBS2Basic)
type instance Output RpcMailboxGetStatus = Either MailboxServiceError (Maybe (MailBoxStatusPayload 'HBS2Basic))
type instance Input RpcMailboxList = () type instance Input RpcMailboxList = ()
type instance Output RpcMailboxList = [(MailboxRefKey 'HBS2Basic, MailboxType)] type instance Output RpcMailboxList = [(MailboxRefKey 'HBS2Basic, MailboxType)]