hbs2/hbs2-peer/lib/HBS2/Peer/Proto/Mailbox.hs

175 lines
5.2 KiB
Haskell

{-# Language UndecidableInstances #-}
{-# Language AllowAmbiguousTypes #-}
module HBS2.Peer.Proto.Mailbox
( module HBS2.Peer.Proto.Mailbox
, module HBS2.Peer.Proto.Mailbox.Message
) where
import HBS2.Prelude.Plated
import HBS2.Hash
import HBS2.Data.Types.Refs
import HBS2.Data.Types.SignedBox
import HBS2.Storage
import HBS2.Actors.Peer.Types
import HBS2.Peer.Proto.Mailbox.Types
import HBS2.Peer.Proto.Mailbox.Message
import HBS2.Peer.Proto.Mailbox.Entry
import Data.Maybe
import Control.Monad.Trans.Cont
import Codec.Serialise
data MailBoxStatusPayload s =
MailBoxStatusPayload
{ mbsMailboxKey :: MailboxKey s
, mbsMailboxHash :: HashRef
}
deriving stock (Generic)
data SetPolicyPayload s =
SetPolicyPayload
{ sppMailboxKey :: MailboxKey s
, sppPolicyVersion :: PolicyVersion
, sppPolicyRef :: HashRef
}
deriving stock (Generic)
data GetPolicyPayload s =
GetPolicyPayload
{ gppMailboxKey :: MailboxKey s
, gppPolicyVersion :: PolicyVersion
, gppPolicyRef :: HashRef
}
deriving stock (Generic)
data DeleteMessagesPayload s =
DeleteMessagesPayload
{ dmpMailboxKey :: MailboxKey s
, dmpPredicate :: MailboxMessagePredicate
}
deriving stock (Generic)
data MailBoxProtoMessage s e =
SendMessage (Message s) -- already has signed box
| CheckMailbox (SignedBox (MailboxKey s) s)
| MailboxStatus (SignedBox (MailBoxStatusPayload s) s)
| SetPolicy (SignedBox (SetPolicyPayload s) s)
| GetPolicy (SignedBox (GetPolicyPayload s) s)
| CurrentPolicy (GetPolicyPayload s)
| DeleteMessages (SignedBox (DeleteMessagesPayload s) s)
deriving stock (Generic)
data MailBoxProto s e =
MailBoxProtoV1 { mailBoxProtoPayload :: MailBoxProtoMessage s e }
deriving stock (Generic)
instance ForMailbox s => Serialise (MailBoxStatusPayload s)
instance ForMailbox s => Serialise (SetPolicyPayload s)
instance ForMailbox s => Serialise (GetPolicyPayload s)
instance ForMailbox s => Serialise (DeleteMessagesPayload s)
instance ForMailbox s => Serialise (MailBoxProtoMessage s e)
instance ForMailbox s => Serialise (MailBoxProto s e)
class IsMailboxProtoAdapter s a where
mailboxGetStorage :: forall m . MonadIO m => a -> m AnyStorage
mailboxAcceptMessage :: forall m . (ForMailbox s, MonadIO m)
=> a
-> Message s
-> MessageContent s
-> m ()
mailboxProto :: forall e s m p a . ( MonadIO m
, Response e p m
, HasDeferred p e m
, HasGossip e p m
, IsMailboxProtoAdapter s a
, p ~ MailBoxProto s e
, s ~ Encryption e
, ForMailbox s
)
=> a
-> MailBoxProto (Encryption e) e
-> m ()
mailboxProto adapter mess = do
-- common stuff
sto <- mailboxGetStorage @s adapter
now <- liftIO $ getPOSIXTime <&> round
case mailBoxProtoPayload mess of
SendMessage msg -> deferred @p do
-- TODO: implement-SendMessage
-- [ ] check-if-mailbox-exists
-- [ ] check-message-signature
-- [ ] if-already-processed-then-skip
-- [ ] store-message-hash-block-with-ttl
-- [ ] if-message-to-this-mailbox-then store-message
-- [ ] gossip-message
-- проверяем, что еще не обрабатывали?
-- если обрабатывали -- то дропаем
-- что мы пишем в сторейдж?
-- кто потом это дропает?
flip runContT pure $ callCC \exit -> do
-- проверить подпись быстрее, чем читать диск
let unboxed' = unboxSignedBox0 @(MessageContent s) (messageContent msg)
-- ок, сообщение нормальное, шлём госсип, пишем, что обработали
(_, content) <- ContT $ maybe1 unboxed' none
let h = hashObject @HbSync (serialise msg) & HashRef
let routed = serialise (RoutedEntry h)
let routedHash = hashObject routed
seen <- hasBlock sto routedHash <&> isJust
unless seen $ lift do
gossip mess
mailboxAcceptMessage adapter msg content
-- TODO: expire-block-and-collect-garbage
void $ putBlock sto routed
CheckMailbox{} -> do
-- TODO: implement-CheckMailbox
-- [ ] check-signed-box-or-drop
-- [ ] if-client-has-mailbox-then
-- [ ] get-mailbox-status
-- [ ] answer-MailboxStatus
-- [ ] gossip-message?
none
MailboxStatus{} -> do
-- TODO: implement-MailboxStatus
--
-- [ ] if-do-gossip-setting-then
-- [ ] gossip-MailboxStatus
--
-- [ ] check-signed-box-or-drop
-- [ ] if-client-has-mailbox-then
-- [ ] get-mailbox-status
-- [ ] answer-MailboxStatus
--
none
SetPolicy{} -> do
none
GetPolicy{} -> do
none
CurrentPolicy{} -> do
none
DeleteMessages{} -> do
none