-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | SimpleXMQ message broker -- -- This package includes server, client and agent -- for SMP protocols: -- -- -- -- See terminal chat prototype built with SimpleXMQ broker. @package simplexmq @version 0.3.2 module Simplex.Messaging.Agent.Store.SQLite.Schema createSchema :: Connection -> IO () module Simplex.Messaging.Util newtype InternalException e InternalException :: e -> InternalException e [unInternalException] :: InternalException e -> e raceAny_ :: MonadUnliftIO m => [m a] -> m () (<$$>) :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b) infixl 4 <$$> (<$?>) :: MonadFail m => (a -> Either String b) -> m a -> m b infixl 4 <$?> bshow :: Show a => a -> ByteString liftIOEither :: (MonadIO m, MonadError e m) => IO (Either e a) -> m a liftError :: (MonadIO m, MonadError e' m) => (e -> e') -> ExceptT e IO a -> m a liftEitherError :: (MonadIO m, MonadError e' m) => (e -> e') -> IO (Either e a) -> m a instance GHC.Show.Show e => GHC.Show.Show (Simplex.Messaging.Util.InternalException e) instance GHC.Classes.Eq e => GHC.Classes.Eq (Simplex.Messaging.Util.InternalException e) instance GHC.Exception.Type.Exception e => GHC.Exception.Type.Exception (Simplex.Messaging.Util.InternalException e) instance (Control.Monad.IO.Unlift.MonadUnliftIO m, GHC.Exception.Type.Exception e) => Control.Monad.IO.Unlift.MonadUnliftIO (Control.Monad.Trans.Except.ExceptT e m) module Simplex.Messaging.Parsers base64P :: Parser ByteString base64StringP :: Parser ByteString tsISO8601P :: Parser UTCTime parse :: Parser a -> e -> ByteString -> Either e a parseAll :: Parser a -> ByteString -> Either String a parseRead :: Read a => Parser ByteString -> Parser a parseRead1 :: Read a => Parser a parseRead2 :: Read a => Parser a parseString :: (ByteString -> Either String a) -> String -> a blobFieldParser :: Typeable k => Parser k -> FieldParser k -- | This module provides cryptography implementation for SMP protocols -- based on cryptonite package. module Simplex.Messaging.Crypto -- | Type-class used for both private key types: SafePrivateKey and -- FullPrivateKey. class PrivateKey k rsaPrivateKey :: PrivateKey k => k -> PrivateKey -- | A newtype of PrivateKey, with PublicKey removed. -- -- It is not possible to recover PublicKey from SafePrivateKey. The -- constructor of this type is not exported. data SafePrivateKey -- | A newtype of PrivateKey (with PublicKey inside). newtype FullPrivateKey FullPrivateKey :: PrivateKey -> FullPrivateKey [$sel:unPrivateKey:FullPrivateKey] :: FullPrivateKey -> PrivateKey -- | A newtype of PublicKey. newtype PublicKey PublicKey :: PublicKey -> PublicKey [$sel:rsaPublicKey:PublicKey] :: PublicKey -> PublicKey -- | Tuple of RSA PublicKey and SafePrivateKey. type SafeKeyPair = (PublicKey, SafePrivateKey) -- | Tuple of RSA PublicKey and FullPrivateKey. type FullKeyPair = (PublicKey, FullPrivateKey) -- | Key hash newtype. newtype KeyHash KeyHash :: ByteString -> KeyHash [$sel:unKeyHash:KeyHash] :: KeyHash -> ByteString -- | Generate RSA key pair with either SafePrivateKey or FullPrivateKey. generateKeyPair :: PrivateKey k => Int -> IO (KeyPair k) publicKey :: FullPrivateKey -> PublicKey publicKeySize :: PublicKey -> Int validKeySize :: Int -> Bool -- | Construct SafePrivateKey from three numbers - used internally -- and in the tests. safePrivateKey :: (Int, Integer, Integer) -> SafePrivateKey -- | E2E encrypt SMP agent messages. -- -- -- https://github.com/simplex-chat/simplexmq/blob/master/rfcs/2021-01-26-crypto.md#e2e-encryption encrypt :: PublicKey -> Int -> ByteString -> ExceptT CryptoError IO ByteString -- | E2E decrypt SMP agent messages. -- -- -- https://github.com/simplex-chat/simplexmq/blob/master/rfcs/2021-01-26-crypto.md#e2e-encryption decrypt :: PrivateKey k => k -> ByteString -> ExceptT CryptoError IO ByteString -- | RSA OAEP encryption. -- -- Used as part of hybrid E2E encryption scheme and for SMP transport -- handshake. encryptOAEP :: PublicKey -> ByteString -> ExceptT CryptoError IO ByteString -- | RSA OAEP decryption. -- -- Used as part of hybrid E2E encryption scheme and for SMP transport -- handshake. decryptOAEP :: PrivateKey k => k -> ByteString -> ExceptT CryptoError IO ByteString -- | RSA signature newtype. newtype Signature Signature :: ByteString -> Signature [$sel:unSignature:Signature] :: Signature -> ByteString -- | RSA PSS message signing. -- -- Used by SMP clients to sign SMP commands and by SMP agents to sign -- messages. sign :: PrivateKey k => k -> ByteString -> ExceptT CryptoError IO Signature -- | RSA PSS signature verification. -- -- Used by SMP servers to authorize SMP commands and by SMP agents to -- verify messages. verify :: PublicKey -> Signature -> ByteString -> Bool -- | AES key newtype. newtype Key Key :: ByteString -> Key [$sel:unKey:Key] :: Key -> ByteString -- | IV bytes newtype. newtype IV IV :: ByteString -> IV [$sel:unIV:IV] :: IV -> ByteString -- | AEAD-GCM encryption. -- -- Used as part of hybrid E2E encryption scheme and for SMP transport -- blocks encryption. encryptAES :: Key -> IV -> Int -> ByteString -> ExceptT CryptoError IO (AuthTag, ByteString) -- | AEAD-GCM decryption. -- -- Used as part of hybrid E2E encryption scheme and for SMP transport -- blocks decryption. decryptAES :: Key -> IV -> ByteString -> AuthTag -> ExceptT CryptoError IO ByteString authTagSize :: Int -- | Convert AEAD AuthTag to ByteString. authTagToBS :: AuthTag -> ByteString -- | Convert ByteString to AEAD AuthTag. bsToAuthTag :: ByteString -> AuthTag -- | Random AES256 key. randomAesKey :: IO Key -- | Random IV bytes for AES256 encryption. randomIV :: IO IV -- | AES256 key parser. aesKeyP :: Parser Key -- | IV bytes parser. ivP :: Parser IV -- | Base-64 PKCS8 encoding of PSA private key. -- -- Not used as part of SMP protocols. serializePrivKey :: PrivateKey k => k -> ByteString -- | Base-64 X509 encoding of RSA public key. -- -- Used as part of SMP queue information (out-of-band message). serializePubKey :: PublicKey -> ByteString encodePubKey :: PublicKey -> ByteString -- | Digest (hash) of binary X509 encoding of RSA public key. publicKeyHash :: PublicKey -> KeyHash privKeyP :: PrivateKey k => Parser k pubKeyP :: Parser PublicKey binaryPubKeyP :: Parser PublicKey -- | SHA256 digest. sha256Hash :: ByteString -> ByteString -- | Various cryptographic or related errors. data CryptoError -- | RSA OAEP encryption error RSAEncryptError :: Error -> CryptoError -- | RSA OAEP decryption error RSADecryptError :: Error -> CryptoError -- | RSA PSS signature error RSASignError :: Error -> CryptoError -- | AES initialization error AESCipherError :: CryptoError -> CryptoError -- | IV generation error CryptoIVError :: CryptoError -- | AES decryption error AESDecryptError :: CryptoError -- | message does not fit in SMP block CryptoLargeMsgError :: CryptoError -- | failure parsing RSA-encrypted message header CryptoHeaderError :: String -> CryptoError instance GHC.Show.Show Simplex.Messaging.Crypto.PublicKey instance GHC.Classes.Eq Simplex.Messaging.Crypto.PublicKey instance GHC.Show.Show Simplex.Messaging.Crypto.SafePrivateKey instance GHC.Classes.Eq Simplex.Messaging.Crypto.SafePrivateKey instance GHC.Show.Show Simplex.Messaging.Crypto.FullPrivateKey instance GHC.Classes.Eq Simplex.Messaging.Crypto.FullPrivateKey instance GHC.Show.Show Simplex.Messaging.Crypto.Signature instance GHC.Classes.Eq Simplex.Messaging.Crypto.Signature instance GHC.Exception.Type.Exception Simplex.Messaging.Crypto.CryptoError instance GHC.Show.Show Simplex.Messaging.Crypto.CryptoError instance GHC.Classes.Eq Simplex.Messaging.Crypto.CryptoError instance GHC.Show.Show Simplex.Messaging.Crypto.KeyHash instance GHC.Classes.Ord Simplex.Messaging.Crypto.KeyHash instance GHC.Classes.Eq Simplex.Messaging.Crypto.KeyHash instance Data.String.IsString Simplex.Messaging.Crypto.KeyHash instance Database.SQLite.Simple.ToField.ToField Simplex.Messaging.Crypto.KeyHash instance Database.SQLite.Simple.FromField.FromField Simplex.Messaging.Crypto.KeyHash instance Data.String.IsString Simplex.Messaging.Crypto.Signature instance Simplex.Messaging.Crypto.PrivateKey Simplex.Messaging.Crypto.SafePrivateKey instance Simplex.Messaging.Crypto.PrivateKey Simplex.Messaging.Crypto.FullPrivateKey instance Data.String.IsString Simplex.Messaging.Crypto.FullPrivateKey instance Database.SQLite.Simple.ToField.ToField Simplex.Messaging.Crypto.SafePrivateKey instance Database.SQLite.Simple.FromField.FromField Simplex.Messaging.Crypto.SafePrivateKey instance Data.String.IsString Simplex.Messaging.Crypto.PublicKey instance Database.SQLite.Simple.ToField.ToField Simplex.Messaging.Crypto.PublicKey instance Database.SQLite.Simple.FromField.FromField Simplex.Messaging.Crypto.PublicKey -- | This module defines basic TCP server and client and SMP protocol -- encrypted transport over TCP. -- -- See -- https://github.com/simplex-chat/simplexmq/blob/master/protocol/simplex-messaging.md#appendix-a module Simplex.Messaging.Transport class Transport c transport :: Transport c => ATransport transportName :: Transport c => TProxy c -> String -- | Upgrade client socket to connection (used in the server) getServerConnection :: Transport c => Socket -> IO c -- | Upgrade server socket to connection (used in the client) getClientConnection :: Transport c => Socket -> IO c -- | Close connection closeConnection :: Transport c => c -> IO () -- | Read fixed number of bytes from connection cGet :: Transport c => c -> Int -> IO ByteString -- | Write bytes to connection cPut :: Transport c => c -> ByteString -> IO () -- | Receive ByteString from connection, allowing LF or CRLF termination. getLn :: Transport c => c -> IO ByteString -- | Send ByteString to connection terminating it with CRLF. putLn :: Transport c => c -> ByteString -> IO () data TProxy c TProxy :: TProxy c data ATransport ATransport :: TProxy c -> ATransport -- | Run transport server (plain TCP or WebSockets) on passed TCP port and -- signal when server started and stopped via passed TMVar. -- -- All accepted connections are passed to the passed function. runTransportServer :: (Transport c, MonadUnliftIO m) => TMVar Bool -> ServiceName -> (c -> m ()) -> m () -- | Connect to passed TCP host:port and pass handle to the client. runTransportClient :: Transport c => MonadUnliftIO m => HostName -> ServiceName -> (c -> m a) -> m a newtype TCP TCP :: Handle -> TCP [$sel:tcpHandle:TCP] :: TCP -> Handle -- | The handle for SMP encrypted transport connection over Transport . data THandle c THandle :: c -> SessionKey -> SessionKey -> Int -> THandle c [$sel:connection:THandle] :: THandle c -> c [$sel:sndKey:THandle] :: THandle c -> SessionKey [$sel:rcvKey:THandle] :: THandle c -> SessionKey [$sel:blockSize:THandle] :: THandle c -> Int -- | Error of SMP encrypted transport over TCP. data TransportError -- | error parsing transport block TEBadBlock :: TransportError -- | block encryption error TEEncrypt :: TransportError -- | block decryption error TEDecrypt :: TransportError -- | transport handshake error TEHandshake :: HandshakeError -> TransportError -- | Server SMP encrypted transport handshake. -- -- See -- https://github.com/simplex-chat/simplexmq/blob/master/protocol/simplex-messaging.md#appendix-a -- -- The numbers in function names refer to the steps in the document. serverHandshake :: forall c. Transport c => c -> FullKeyPair -> ExceptT TransportError IO (THandle c) -- | Client SMP encrypted transport handshake. -- -- See -- https://github.com/simplex-chat/simplexmq/blob/master/protocol/simplex-messaging.md#appendix-a -- -- The numbers in function names refer to the steps in the document. clientHandshake :: forall c. Transport c => c -> Maybe KeyHash -> ExceptT TransportError IO (THandle c) -- | Encrypt and send block to SMP encrypted transport. tPutEncrypted :: Transport c => THandle c -> ByteString -> IO (Either TransportError ()) -- | Receive and decrypt block from SMP encrypted transport. tGetEncrypted :: Transport c => THandle c -> IO (Either TransportError ByteString) -- | Serialize SMP encrypted transport error. serializeTransportError :: TransportError -> ByteString -- | SMP encrypted transport error parser. transportErrorP :: Parser TransportError -- | Trim trailing CR from ByteString. trimCR :: ByteString -> ByteString instance GHC.Classes.Ord Simplex.Messaging.Transport.SMPVersion instance GHC.Classes.Eq Simplex.Messaging.Transport.SMPVersion instance GHC.Exception.Type.Exception Simplex.Messaging.Transport.HandshakeError instance GHC.Show.Show Simplex.Messaging.Transport.HandshakeError instance GHC.Read.Read Simplex.Messaging.Transport.HandshakeError instance GHC.Generics.Generic Simplex.Messaging.Transport.HandshakeError instance GHC.Classes.Eq Simplex.Messaging.Transport.HandshakeError instance GHC.Exception.Type.Exception Simplex.Messaging.Transport.TransportError instance GHC.Show.Show Simplex.Messaging.Transport.TransportError instance GHC.Read.Read Simplex.Messaging.Transport.TransportError instance GHC.Generics.Generic Simplex.Messaging.Transport.TransportError instance GHC.Classes.Eq Simplex.Messaging.Transport.TransportError instance GHC.Show.Show Simplex.Messaging.Transport.ServerHeader instance GHC.Classes.Eq Simplex.Messaging.Transport.ServerHeader instance Test.QuickCheck.Arbitrary.Arbitrary Simplex.Messaging.Transport.TransportError instance Test.QuickCheck.Arbitrary.Arbitrary Simplex.Messaging.Transport.HandshakeError instance Simplex.Messaging.Transport.Transport Simplex.Messaging.Transport.TCP module Simplex.Messaging.Transport.WebSockets data WS WS :: Stream -> Connection -> WS [wsStream] :: WS -> Stream [wsConnection] :: WS -> Connection instance Simplex.Messaging.Transport.Transport Simplex.Messaging.Transport.WebSockets.WS -- | Types, parsers, serializers and functions to send and receive SMP -- protocol commands and responses. -- -- See -- https://github.com/simplex-chat/simplexmq/blob/master/protocol/simplex-messaging.md module Simplex.Messaging.Protocol -- | Parameterized type for SMP protocol commands from all participants. data Command (a :: Party) [NEW] :: RecipientPublicKey -> Command Recipient [SUB] :: Command Recipient [KEY] :: SenderPublicKey -> Command Recipient [ACK] :: Command Recipient [OFF] :: Command Recipient [DEL] :: Command Recipient [SEND] :: MsgBody -> Command Sender [PING] :: Command Sender [IDS] :: RecipientId -> SenderId -> Command Broker [MSG] :: MsgId -> UTCTime -> MsgBody -> Command Broker [END] :: Command Broker [OK] :: Command Broker [ERR] :: ErrorType -> Command Broker [PONG] :: Command Broker -- | SMP protocol participants. data Party Broker :: Party Recipient :: Party Sender :: Party -- | Type for command or response of any participant. data Cmd Cmd :: SParty a -> Command a -> Cmd -- | Singleton types for SMP protocol participants. data SParty :: Party -> Type [SBroker] :: SParty Broker [SRecipient] :: SParty Recipient [SSender] :: SParty Sender -- | Type for protocol errors. data ErrorType -- | incorrect block format, encoding or signature size BLOCK :: ErrorType -- | SMP command is unknown or has invalid syntax CMD :: CommandError -> ErrorType -- | command authorization error - bad signature or non-existing SMP queue AUTH :: ErrorType -- | ACK command is sent without message to be acknowledged NO_MSG :: ErrorType -- | internal server error INTERNAL :: ErrorType -- | used internally, never returned by the server (to be removed) DUPLICATE_ :: ErrorType -- | SMP command error type. data CommandError -- | server response sent from client or vice versa PROHIBITED :: CommandError -- | bad RSA key size in NEW or KEY commands (only 1024, 2048 and 4096 bits -- keys are allowed) KEY_SIZE :: CommandError -- | error parsing command SYNTAX :: CommandError -- | transmission has no required credentials (signature or queue ID) NO_AUTH :: CommandError -- | transmission has credentials that are not allowed for this command HAS_AUTH :: CommandError -- | transmission has no required queue ID NO_QUEUE :: CommandError -- | SMP transmission without signature. type Transmission = (CorrId, QueueId, Cmd) -- | SMP transmission with signature. type SignedTransmission = (Signature, Transmission) -- | signed parsed transmission, with parsing error. type SignedTransmissionOrError = (Signature, TransmissionOrError) -- | unparsed SMP transmission with signature. type RawTransmission = (ByteString, ByteString, ByteString, ByteString) -- | unparsed SMP transmission with signature. type SignedRawTransmission = (Signature, ByteString) -- | Transmission correlation ID. -- -- A newtype to avoid accidentally changing order of transmission parts. newtype CorrId CorrId :: ByteString -> CorrId [bs] :: CorrId -> ByteString -- | SMP queue ID on the server. type QueueId = Encoded -- | SMP queue ID for the recipient. type RecipientId = QueueId -- | SMP queue ID for the sender. type SenderId = QueueId -- | Recipient's private key used by the recipient to authorize (sign) SMP -- commands. -- -- Only used by SMP agent, kept here so its definition is close to -- respective public key. type RecipientPrivateKey = SafePrivateKey -- | Recipient's public key used by SMP server to verify authorization of -- SMP commands. type RecipientPublicKey = PublicKey -- | Sender's private key used by the recipient to authorize (sign) SMP -- commands. -- -- Only used by SMP agent, kept here so its definition is close to -- respective public key. type SenderPrivateKey = SafePrivateKey -- | Sender's public key used by SMP server to verify authorization of SMP -- commands. type SenderPublicKey = PublicKey -- | Base-64 encoded string. type Encoded = ByteString -- | SMP message server ID. type MsgId = Encoded -- | SMP message body. type MsgBody = ByteString -- | Serialize SMP transmission. serializeTransmission :: Transmission -> ByteString -- | Serialize SMP command. serializeCommand :: Cmd -> ByteString -- | Serialize SMP error. serializeErrorType :: ErrorType -> ByteString -- | SMP transmission parser. transmissionP :: Parser RawTransmission -- | SMP command parser. commandP :: Parser Cmd -- | SMP error parser. errorTypeP :: Parser ErrorType -- | Send signed SMP transmission to TCP transport. tPut :: Transport c => THandle c -> SignedRawTransmission -> IO (Either TransportError ()) -- | Receive client and server transmissions. -- -- The first argument is used to limit allowed senders. fromClient -- or fromServer should be used here. tGet :: forall c m. (Transport c, MonadIO m) => (Cmd -> Either ErrorType Cmd) -> THandle c -> m SignedTransmissionOrError -- | Validate that it is an SMP client command, used with tGet by -- Server. fromClient :: Cmd -> Either ErrorType Cmd -- | Validate that it is an SMP server command, used with tGet by -- Client. fromServer :: Cmd -> Either ErrorType Cmd instance GHC.Show.Show Simplex.Messaging.Protocol.Party instance GHC.Show.Show Simplex.Messaging.Protocol.CorrId instance GHC.Classes.Ord Simplex.Messaging.Protocol.CorrId instance GHC.Classes.Eq Simplex.Messaging.Protocol.CorrId instance GHC.Show.Show Simplex.Messaging.Protocol.CommandError instance GHC.Read.Read Simplex.Messaging.Protocol.CommandError instance GHC.Generics.Generic Simplex.Messaging.Protocol.CommandError instance GHC.Classes.Eq Simplex.Messaging.Protocol.CommandError instance GHC.Show.Show Simplex.Messaging.Protocol.ErrorType instance GHC.Read.Read Simplex.Messaging.Protocol.ErrorType instance GHC.Generics.Generic Simplex.Messaging.Protocol.ErrorType instance GHC.Classes.Eq Simplex.Messaging.Protocol.ErrorType instance GHC.Show.Show (Simplex.Messaging.Protocol.SParty a) instance GHC.Show.Show Simplex.Messaging.Protocol.Cmd instance GHC.Show.Show (Simplex.Messaging.Protocol.Command a) instance GHC.Classes.Eq (Simplex.Messaging.Protocol.Command a) instance Test.QuickCheck.Arbitrary.Arbitrary Simplex.Messaging.Protocol.ErrorType instance Test.QuickCheck.Arbitrary.Arbitrary Simplex.Messaging.Protocol.CommandError instance Data.String.IsString Simplex.Messaging.Protocol.CorrId module Simplex.Messaging.Server.QueueStore data QueueRec QueueRec :: QueueId -> QueueId -> RecipientPublicKey -> Maybe SenderPublicKey -> QueueStatus -> QueueRec [recipientId] :: QueueRec -> QueueId [senderId] :: QueueRec -> QueueId [recipientKey] :: QueueRec -> RecipientPublicKey [senderKey] :: QueueRec -> Maybe SenderPublicKey [status] :: QueueRec -> QueueStatus data QueueStatus QueueActive :: QueueStatus QueueOff :: QueueStatus class MonadQueueStore s m addQueue :: MonadQueueStore s m => s -> RecipientPublicKey -> (RecipientId, SenderId) -> m (Either ErrorType ()) getQueue :: MonadQueueStore s m => s -> SParty (a :: Party) -> QueueId -> m (Either ErrorType QueueRec) secureQueue :: MonadQueueStore s m => s -> RecipientId -> SenderPublicKey -> m (Either ErrorType ()) suspendQueue :: MonadQueueStore s m => s -> RecipientId -> m (Either ErrorType ()) deleteQueue :: MonadQueueStore s m => s -> RecipientId -> m (Either ErrorType ()) mkQueueRec :: RecipientPublicKey -> (RecipientId, SenderId) -> QueueRec instance GHC.Classes.Eq Simplex.Messaging.Server.QueueStore.QueueStatus module Simplex.Messaging.Server.StoreLog -- | opaque container for file handle with a type-safe IOMode constructors -- are not exported, openWriteStoreLog and openReadStoreLog should be -- used instead data StoreLog (a :: IOMode) openWriteStoreLog :: FilePath -> IO (StoreLog 'WriteMode) openReadStoreLog :: FilePath -> IO (StoreLog 'ReadMode) storeLogFilePath :: StoreLog a -> FilePath closeStoreLog :: StoreLog a -> IO () logCreateQueue :: StoreLog 'WriteMode -> QueueRec -> IO () logSecureQueue :: StoreLog 'WriteMode -> QueueId -> SenderPublicKey -> IO () logDeleteQueue :: StoreLog 'WriteMode -> QueueId -> IO () readWriteStoreLog :: StoreLog 'ReadMode -> IO (Map RecipientId QueueRec, StoreLog 'WriteMode) module Simplex.Messaging.Server.QueueStore.STM data QueueStoreData QueueStoreData :: Map RecipientId QueueRec -> Map SenderId RecipientId -> QueueStoreData [queues] :: QueueStoreData -> Map RecipientId QueueRec [senders] :: QueueStoreData -> Map SenderId RecipientId type QueueStore = TVar QueueStoreData newQueueStore :: STM QueueStore updateQueues :: QueueStore -> RecipientId -> (QueueStoreData -> QueueRec -> (Either ErrorType (), QueueStoreData)) -> STM (Either ErrorType ()) getRcpQueue :: QueueStoreData -> RecipientId -> Either ErrorType QueueRec instance Simplex.Messaging.Server.QueueStore.MonadQueueStore Simplex.Messaging.Server.QueueStore.STM.QueueStore GHC.Conc.Sync.STM module Simplex.Messaging.Server.MsgStore data Message Message :: Encoded -> UTCTime -> MsgBody -> Message [msgId] :: Message -> Encoded [ts] :: Message -> UTCTime [msgBody] :: Message -> MsgBody class MonadMsgStore s q m | s -> q getMsgQueue :: MonadMsgStore s q m => s -> RecipientId -> m q delMsgQueue :: MonadMsgStore s q m => s -> RecipientId -> m () class MonadMsgQueue q m writeMsg :: MonadMsgQueue q m => q -> Message -> m () tryPeekMsg :: MonadMsgQueue q m => q -> m (Maybe Message) peekMsg :: MonadMsgQueue q m => q -> m Message tryDelPeekMsg :: MonadMsgQueue q m => q -> m (Maybe Message) module Simplex.Messaging.Server.MsgStore.STM newtype MsgQueue MsgQueue :: TQueue Message -> MsgQueue [msgQueue] :: MsgQueue -> TQueue Message newtype MsgStoreData MsgStoreData :: Map RecipientId MsgQueue -> MsgStoreData [messages] :: MsgStoreData -> Map RecipientId MsgQueue type STMMsgStore = TVar MsgStoreData newMsgStore :: STM STMMsgStore instance Simplex.Messaging.Server.MsgStore.MonadMsgStore Simplex.Messaging.Server.MsgStore.STM.STMMsgStore Simplex.Messaging.Server.MsgStore.STM.MsgQueue GHC.Conc.Sync.STM instance Simplex.Messaging.Server.MsgStore.MonadMsgQueue Simplex.Messaging.Server.MsgStore.STM.MsgQueue GHC.Conc.Sync.STM module Simplex.Messaging.Server.Env.STM data ServerConfig ServerConfig :: [(ServiceName, ATransport)] -> Natural -> Int -> Int -> Maybe (StoreLog 'ReadMode) -> FullPrivateKey -> ServerConfig [$sel:transports:ServerConfig] :: ServerConfig -> [(ServiceName, ATransport)] [$sel:tbqSize:ServerConfig] :: ServerConfig -> Natural [$sel:queueIdBytes:ServerConfig] :: ServerConfig -> Int [$sel:msgIdBytes:ServerConfig] :: ServerConfig -> Int [$sel:storeLog:ServerConfig] :: ServerConfig -> Maybe (StoreLog 'ReadMode) [$sel:serverPrivateKey:ServerConfig] :: ServerConfig -> FullPrivateKey data Env Env :: ServerConfig -> Server -> QueueStore -> STMMsgStore -> TVar ChaChaDRG -> FullKeyPair -> Maybe (StoreLog 'WriteMode) -> Env [$sel:config:Env] :: Env -> ServerConfig [$sel:server:Env] :: Env -> Server [$sel:queueStore:Env] :: Env -> QueueStore [$sel:msgStore:Env] :: Env -> STMMsgStore [$sel:idsDrg:Env] :: Env -> TVar ChaChaDRG [$sel:serverKeyPair:Env] :: Env -> FullKeyPair [$sel:storeLog:Env] :: Env -> Maybe (StoreLog 'WriteMode) data Server Server :: TBQueue (RecipientId, Client) -> TVar (Map RecipientId Client) -> Server [$sel:subscribedQ:Server] :: Server -> TBQueue (RecipientId, Client) [$sel:subscribers:Server] :: Server -> TVar (Map RecipientId Client) data Client Client :: TVar (Map RecipientId Sub) -> TBQueue Transmission -> TBQueue Transmission -> Client [$sel:subscriptions:Client] :: Client -> TVar (Map RecipientId Sub) [$sel:rcvQ:Client] :: Client -> TBQueue Transmission [$sel:sndQ:Client] :: Client -> TBQueue Transmission data SubscriptionThread NoSub :: SubscriptionThread SubPending :: SubscriptionThread SubThread :: ThreadId -> SubscriptionThread data Sub Sub :: SubscriptionThread -> TMVar () -> Sub [$sel:subThread:Sub] :: Sub -> SubscriptionThread [$sel:delivered:Sub] :: Sub -> TMVar () newServer :: Natural -> STM Server newClient :: Natural -> STM Client newSubscription :: STM Sub newEnv :: forall m. (MonadUnliftIO m, MonadRandom m) => ServerConfig -> m Env -- | This module defines SMP protocol server with in-memory persistence and -- optional append only log of SMP queue records. -- -- See -- https://github.com/simplex-chat/simplexmq/blob/master/protocol/simplex-messaging.md module Simplex.Messaging.Server -- | Runs an SMP server using passed configuration. -- -- See a full server here: -- https://github.com/simplex-chat/simplexmq/blob/master/apps/smp-server/Main.hs runSMPServer :: (MonadRandom m, MonadUnliftIO m) => ServerConfig -> m () -- | Runs an SMP server using passed configuration with signalling. -- -- This function uses passed TMVar to signal when the server is ready to -- accept TCP requests (True) and when it is disconnected from the TCP -- socket once the server thread is killed (False). runSMPServerBlocking :: (MonadRandom m, MonadUnliftIO m) => TMVar Bool -> ServerConfig -> m () -- | Types, parsers, serializers and functions to send and receive SMP -- agent protocol commands and responses. -- -- See -- https://github.com/simplex-chat/simplexmq/blob/master/protocol/agent-protocol.md module Simplex.Messaging.Agent.Protocol -- | Parameterized type for SMP agent protocol commands and responses from -- all participants. data ACommand (p :: AParty) [NEW] :: ACommand Client [INV] :: SMPQueueInfo -> ACommand Agent [JOIN] :: SMPQueueInfo -> ReplyMode -> ACommand Client [CON] :: ACommand Agent [SUB] :: ACommand Client [SUBALL] :: ACommand Client [END] :: ACommand Agent [SEND] :: MsgBody -> ACommand Client [SENT] :: AgentMsgId -> ACommand Agent [MSG] :: {recipientMeta :: (AgentMsgId, UTCTime), brokerMeta :: (MsgId, UTCTime), senderMeta :: (AgentMsgId, UTCTime), msgIntegrity :: MsgIntegrity, msgBody :: MsgBody} -> ACommand Agent [OFF] :: ACommand Client [DEL] :: ACommand Client [OK] :: ACommand Agent [ERR] :: AgentErrorType -> ACommand Agent -- | SMP agent protocol participants. data AParty Agent :: AParty Client :: AParty -- | Singleton types for SMP agent protocol participants. data SAParty :: AParty -> Type [SAgent] :: SAParty Agent [SClient] :: SAParty Client -- | SMP message formats. data SMPMessage -- | SMP confirmation (see SMP protocol) SMPConfirmation :: SenderPublicKey -> SMPMessage -- | Agent message header and envelope for client messages (see SMP -- agent protocol) SMPMessage :: AgentMsgId -> SenderTimestamp -> ByteString -> AMessage -> SMPMessage -- | sequential ID assigned by the sending agent [senderMsgId] :: SMPMessage -> AgentMsgId -- | timestamp from the sending agent [senderTimestamp] :: SMPMessage -> SenderTimestamp -- | digest of the previous message [previousMsgHash] :: SMPMessage -> ByteString -- | messages sent between agents once queue is secured [agentMessage] :: SMPMessage -> AMessage -- | Messages sent between SMP agents once SMP queue is secured. -- -- -- https://github.com/simplex-chat/simplexmq/blob/master/protocol/agent-protocol.md#messages-between-smp-agents data AMessage -- | the first message in the queue to validate it is secured [HELLO] :: VerificationKey -> AckMode -> AMessage -- | reply queue information [REPLY] :: SMPQueueInfo -> AMessage -- | agent envelope for the client message [A_MSG] :: MsgBody -> AMessage -- | SMP server location and transport key digest (hash). data SMPServer SMPServer :: HostName -> Maybe ServiceName -> Maybe KeyHash -> SMPServer [host] :: SMPServer -> HostName [port] :: SMPServer -> Maybe ServiceName [keyHash] :: SMPServer -> Maybe KeyHash -- | SMP queue information sent out-of-band. -- -- -- https://github.com/simplex-chat/simplexmq/blob/master/protocol/simplex-messaging.md#out-of-band-messages data SMPQueueInfo SMPQueueInfo :: SMPServer -> SenderId -> EncryptionKey -> SMPQueueInfo -- | Error type used in errors sent to agent clients. data AgentErrorType -- | command or response error CMD :: CommandErrorType -> AgentErrorType -- | connection errors CONN :: ConnectionErrorType -> AgentErrorType -- | SMP protocol errors forwarded to agent clients SMP :: ErrorType -> AgentErrorType -- | SMP server errors BROKER :: BrokerErrorType -> AgentErrorType -- | errors of other agents AGENT :: SMPAgentError -> AgentErrorType -- | agent implementation or dependency errors INTERNAL :: String -> AgentErrorType -- | SMP agent protocol command or response error. data CommandErrorType -- | command is prohibited PROHIBITED :: CommandErrorType -- | command syntax is invalid SYNTAX :: CommandErrorType -- | connection alias is required with this command NO_CONN :: CommandErrorType -- | message size is not correct (no terminating space) SIZE :: CommandErrorType -- | message does not fit in SMP block LARGE :: CommandErrorType -- | Connection error. data ConnectionErrorType -- | connection alias is not in the database UNKNOWN :: ConnectionErrorType -- | connection alias already exists DUPLICATE :: ConnectionErrorType -- | connection is simplex, but operation requires another queue SIMPLEX :: ConnectionErrorType -- | SMP server errors. data BrokerErrorType -- | invalid server response (failed to parse) RESPONSE :: ErrorType -> BrokerErrorType -- | unexpected response UNEXPECTED :: BrokerErrorType -- | network error NETWORK :: BrokerErrorType -- | handshake or other transport error TRANSPORT :: TransportError -> BrokerErrorType -- | command response timeout TIMEOUT :: BrokerErrorType -- | Errors of another SMP agent. data SMPAgentError -- | possibly should include bytestring that failed to parse A_MESSAGE :: SMPAgentError -- | possibly should include the prohibited SMP/agent message A_PROHIBITED :: SMPAgentError -- | cannot RSA/AES-decrypt or parse decrypted header A_ENCRYPTION :: SMPAgentError -- | invalid RSA signature A_SIGNATURE :: SMPAgentError -- | Parsed SMP agent protocol transmission. type ATransmission p = (CorrId, ConnAlias, ACommand p) -- | SMP agent protocol transmission or transmission error. type ATransmissionOrError p = (CorrId, ConnAlias, Either AgentErrorType (ACommand p)) -- | Raw (unparsed) SMP agent protocol transmission. type ARawTransmission = (ByteString, ByteString, ByteString) -- | SMP agent connection alias. type ConnAlias = ByteString -- | Connection reply mode (used in JOIN command). newtype ReplyMode ReplyMode :: OnOff -> ReplyMode -- | Message acknowledgement mode of the connection. newtype AckMode AckMode :: OnOff -> AckMode -- | Connection modes. data OnOff On :: OnOff Off :: OnOff -- | Result of received message integrity validation. data MsgIntegrity MsgOk :: MsgIntegrity MsgError :: MsgErrorType -> MsgIntegrity -- | Error of message integrity validation. data MsgErrorType MsgSkipped :: AgentMsgId -> AgentMsgId -> MsgErrorType MsgBadId :: AgentMsgId -> MsgErrorType MsgBadHash :: MsgErrorType MsgDuplicate :: MsgErrorType -- | SMP queue status. data QueueStatus -- | queue is created New :: QueueStatus -- | queue is confirmed by the sender Confirmed :: QueueStatus -- | queue is secured with sender key (only used by the queue recipient) Secured :: QueueStatus -- | queue is active Active :: QueueStatus -- | queue is disabled (only used by the queue recipient) Disabled :: QueueStatus -- | Private key used to sign SMP commands type SignatureKey = SafePrivateKey -- | Public key used by SMP server to authorize (verify) SMP commands. type VerificationKey = PublicKey -- | Public key used to E2E encrypt SMP messages. type EncryptionKey = PublicKey -- | Private key used to E2E decrypt SMP messages. type DecryptionKey = SafePrivateKey -- | Serialize SMP agent command. serializeCommand :: ACommand p -> ByteString -- | Serialize SMP message. serializeSMPMessage :: SMPMessage -> ByteString -- | Serialize message integrity validation result. serializeMsgIntegrity :: MsgIntegrity -> ByteString -- | Serialize SMP server location. serializeServer :: SMPServer -> ByteString -- | Serialize SMP queue information that is sent out-of-band. serializeSmpQueueInfo :: SMPQueueInfo -> ByteString -- | Serialize SMP agent protocol error. serializeAgentError :: AgentErrorType -> ByteString -- | AMP agent command and response parser commandP :: Parser ACmd -- | Parse SMP message. parseSMPMessage :: ByteString -> Either AgentErrorType SMPMessage -- | SMP server location parser. smpServerP :: Parser SMPServer -- | SMP queue information parser. smpQueueInfoP :: Parser SMPQueueInfo -- | Message integrity validation result parser. msgIntegrityP :: Parser MsgIntegrity -- | SMP agent protocol error parser. agentErrorTypeP :: Parser AgentErrorType -- | Send SMP agent protocol command (or response) to TCP connection. tPut :: (Transport c, MonadIO m) => c -> ATransmission p -> m () -- | Receive client and agent transmissions from TCP connection. tGet :: forall c m p. (Transport c, MonadIO m) => SAParty p -> c -> m (ATransmissionOrError p) -- | Send raw (unparsed) SMP agent protocol transmission to TCP connection. tPutRaw :: Transport c => c -> ARawTransmission -> IO () -- | Receive raw (unparsed) SMP agent protocol transmission from TCP -- connection. tGetRaw :: Transport c => c -> IO ARawTransmission instance GHC.Show.Show Simplex.Messaging.Agent.Protocol.AParty instance GHC.Classes.Eq Simplex.Messaging.Agent.Protocol.AParty instance GHC.Show.Show Simplex.Messaging.Agent.Protocol.SMPServer instance GHC.Classes.Ord Simplex.Messaging.Agent.Protocol.SMPServer instance GHC.Classes.Eq Simplex.Messaging.Agent.Protocol.SMPServer instance GHC.Read.Read Simplex.Messaging.Agent.Protocol.OnOff instance GHC.Show.Show Simplex.Messaging.Agent.Protocol.OnOff instance GHC.Classes.Eq Simplex.Messaging.Agent.Protocol.OnOff instance GHC.Show.Show Simplex.Messaging.Agent.Protocol.AckMode instance GHC.Classes.Eq Simplex.Messaging.Agent.Protocol.AckMode instance GHC.Show.Show Simplex.Messaging.Agent.Protocol.ReplyMode instance GHC.Classes.Eq Simplex.Messaging.Agent.Protocol.ReplyMode instance GHC.Show.Show Simplex.Messaging.Agent.Protocol.SMPQueueInfo instance GHC.Classes.Eq Simplex.Messaging.Agent.Protocol.SMPQueueInfo instance GHC.Show.Show Simplex.Messaging.Agent.Protocol.AMessage instance GHC.Show.Show Simplex.Messaging.Agent.Protocol.QueueDirection instance GHC.Read.Read Simplex.Messaging.Agent.Protocol.QueueStatus instance GHC.Show.Show Simplex.Messaging.Agent.Protocol.QueueStatus instance GHC.Classes.Eq Simplex.Messaging.Agent.Protocol.QueueStatus instance GHC.Show.Show Simplex.Messaging.Agent.Protocol.SMPMessage instance GHC.Show.Show Simplex.Messaging.Agent.Protocol.MsgErrorType instance GHC.Classes.Eq Simplex.Messaging.Agent.Protocol.MsgErrorType instance GHC.Show.Show Simplex.Messaging.Agent.Protocol.MsgIntegrity instance GHC.Classes.Eq Simplex.Messaging.Agent.Protocol.MsgIntegrity instance GHC.Exception.Type.Exception Simplex.Messaging.Agent.Protocol.CommandErrorType instance GHC.Show.Show Simplex.Messaging.Agent.Protocol.CommandErrorType instance GHC.Read.Read Simplex.Messaging.Agent.Protocol.CommandErrorType instance GHC.Generics.Generic Simplex.Messaging.Agent.Protocol.CommandErrorType instance GHC.Classes.Eq Simplex.Messaging.Agent.Protocol.CommandErrorType instance GHC.Exception.Type.Exception Simplex.Messaging.Agent.Protocol.ConnectionErrorType instance GHC.Show.Show Simplex.Messaging.Agent.Protocol.ConnectionErrorType instance GHC.Read.Read Simplex.Messaging.Agent.Protocol.ConnectionErrorType instance GHC.Generics.Generic Simplex.Messaging.Agent.Protocol.ConnectionErrorType instance GHC.Classes.Eq Simplex.Messaging.Agent.Protocol.ConnectionErrorType instance GHC.Exception.Type.Exception Simplex.Messaging.Agent.Protocol.BrokerErrorType instance GHC.Show.Show Simplex.Messaging.Agent.Protocol.BrokerErrorType instance GHC.Read.Read Simplex.Messaging.Agent.Protocol.BrokerErrorType instance GHC.Generics.Generic Simplex.Messaging.Agent.Protocol.BrokerErrorType instance GHC.Classes.Eq Simplex.Messaging.Agent.Protocol.BrokerErrorType instance GHC.Exception.Type.Exception Simplex.Messaging.Agent.Protocol.SMPAgentError instance GHC.Show.Show Simplex.Messaging.Agent.Protocol.SMPAgentError instance GHC.Read.Read Simplex.Messaging.Agent.Protocol.SMPAgentError instance GHC.Generics.Generic Simplex.Messaging.Agent.Protocol.SMPAgentError instance GHC.Classes.Eq Simplex.Messaging.Agent.Protocol.SMPAgentError instance GHC.Exception.Type.Exception Simplex.Messaging.Agent.Protocol.AgentErrorType instance GHC.Show.Show Simplex.Messaging.Agent.Protocol.AgentErrorType instance GHC.Read.Read Simplex.Messaging.Agent.Protocol.AgentErrorType instance GHC.Generics.Generic Simplex.Messaging.Agent.Protocol.AgentErrorType instance GHC.Classes.Eq Simplex.Messaging.Agent.Protocol.AgentErrorType instance GHC.Show.Show (Simplex.Messaging.Agent.Protocol.SAParty p) instance GHC.Classes.Eq (Simplex.Messaging.Agent.Protocol.SAParty p) instance GHC.Show.Show Simplex.Messaging.Agent.Protocol.ACmd instance GHC.Classes.Eq (Simplex.Messaging.Agent.Protocol.ACommand p) instance GHC.Show.Show (Simplex.Messaging.Agent.Protocol.ACommand p) instance Test.QuickCheck.Arbitrary.Arbitrary Simplex.Messaging.Agent.Protocol.AgentErrorType instance Test.QuickCheck.Arbitrary.Arbitrary Simplex.Messaging.Agent.Protocol.SMPAgentError instance Test.QuickCheck.Arbitrary.Arbitrary Simplex.Messaging.Agent.Protocol.BrokerErrorType instance Test.QuickCheck.Arbitrary.Arbitrary Simplex.Messaging.Agent.Protocol.ConnectionErrorType instance Test.QuickCheck.Arbitrary.Arbitrary Simplex.Messaging.Agent.Protocol.CommandErrorType instance Data.String.IsString Simplex.Messaging.Agent.Protocol.SMPServer instance Data.Type.Equality.TestEquality Simplex.Messaging.Agent.Protocol.SAParty -- | This module provides a functional client API for SMP protocol. -- -- See -- https://github.com/simplex-chat/simplexmq/blob/master/protocol/simplex-messaging.md module Simplex.Messaging.Client -- | SMPClient is a handle used to send commands to a specific SMP -- server. -- -- The only exported selector is blockSize that is negotiated with the -- server during the TCP transport handshake. -- -- Use getSMPClient to connect to an SMP server and create a -- client handle. data SMPClient -- | Connects to SMPServer using passed client configuration and -- queue for messages and notifications. -- -- A single queue can be used for multiple SMPClient instances, as -- SMPServerTransmission includes server information. getSMPClient :: SMPServer -> SMPClientConfig -> TBQueue SMPServerTransmission -> IO () -> IO (Either SMPClientError SMPClient) -- | Disconnects SMP client from the server and terminates client threads. closeSMPClient :: SMPClient -> IO () -- | Create a new SMP queue. -- -- -- https://github.com/simplex-chat/simplexmq/blob/master/protocol/simplex-messaging.md#create-queue-command createSMPQueue :: SMPClient -> RecipientPrivateKey -> RecipientPublicKey -> ExceptT SMPClientError IO (RecipientId, SenderId) -- | Subscribe to the SMP queue. -- -- -- https://github.com/simplex-chat/simplexmq/blob/master/protocol/simplex-messaging.md#subscribe-to-queue subscribeSMPQueue :: SMPClient -> RecipientPrivateKey -> RecipientId -> ExceptT SMPClientError IO () -- | Secure the SMP queue by adding a sender public key. -- -- -- https://github.com/simplex-chat/simplexmq/blob/master/protocol/simplex-messaging.md#secure-queue-command secureSMPQueue :: SMPClient -> RecipientPrivateKey -> RecipientId -> SenderPublicKey -> ExceptT SMPClientError IO () -- | Send SMP message. -- -- -- https://github.com/simplex-chat/simplexmq/blob/master/protocol/simplex-messaging.md#send-message sendSMPMessage :: SMPClient -> Maybe SenderPrivateKey -> SenderId -> MsgBody -> ExceptT SMPClientError IO () -- | Acknowledge message delivery (server deletes the message). -- -- -- https://github.com/simplex-chat/simplexmq/blob/master/protocol/simplex-messaging.md#acknowledge-message-delivery ackSMPMessage :: SMPClient -> RecipientPrivateKey -> QueueId -> ExceptT SMPClientError IO () -- | Irreversibly suspend SMP queue. The existing messages from the queue -- will still be delivered. -- -- -- https://github.com/simplex-chat/simplexmq/blob/master/protocol/simplex-messaging.md#suspend-queue suspendSMPQueue :: SMPClient -> RecipientPrivateKey -> QueueId -> ExceptT SMPClientError IO () -- | Irreversibly delete SMP queue and all messages in it. -- -- -- https://github.com/simplex-chat/simplexmq/blob/master/protocol/simplex-messaging.md#delete-queue deleteSMPQueue :: SMPClient -> RecipientPrivateKey -> QueueId -> ExceptT SMPClientError IO () -- | Send any SMP command (Cmd type). sendSMPCommand :: SMPClient -> Maybe SafePrivateKey -> QueueId -> Cmd -> ExceptT SMPClientError IO Cmd -- | SMP client error type. data SMPClientError -- | Correctly parsed SMP server ERR response. This error is forwarded to -- the agent client as `ERR SMP err`. SMPServerError :: ErrorType -> SMPClientError -- | Invalid server response that failed to parse. Forwarded to the agent -- client as `ERR BROKER RESPONSE`. SMPResponseError :: ErrorType -> SMPClientError -- | Different response from what is expected to a certain SMP command, -- e.g. server should respond IDS or ERR to NEW -- command, other responses would result in this error. Forwarded to the -- agent client as `ERR BROKER UNEXPECTED`. SMPUnexpectedResponse :: SMPClientError -- | Used for TCP connection and command response timeouts. Forwarded to -- the agent client as `ERR BROKER TIMEOUT`. SMPResponseTimeout :: SMPClientError -- | Failure to establish TCP connection. Forwarded to the agent client as -- `ERR BROKER NETWORK`. SMPNetworkError :: SMPClientError -- | TCP transport handshake or some other transport error. Forwarded to -- the agent client as `ERR BROKER TRANSPORT e`. SMPTransportError :: TransportError -> SMPClientError -- | Error when cryptographically "signing" the command. SMPSignatureError :: CryptoError -> SMPClientError -- | SMP client configuration. data SMPClientConfig SMPClientConfig :: Natural -> (ServiceName, ATransport) -> Int -> Int -> Int -> SMPClientConfig -- | size of TBQueue to use for server commands and responses [$sel:qSize:SMPClientConfig] :: SMPClientConfig -> Natural -- | default SMP server port if port is not specified in SMPServer [$sel:defaultTransport:SMPClientConfig] :: SMPClientConfig -> (ServiceName, ATransport) -- | timeout of TCP commands (microseconds) [$sel:tcpTimeout:SMPClientConfig] :: SMPClientConfig -> Int -- | period for SMP ping commands (microseconds) [$sel:smpPing:SMPClientConfig] :: SMPClientConfig -> Int -- | estimated maximum size of SMP command excluding message body, -- determines the maximum allowed message size [$sel:smpCommandSize:SMPClientConfig] :: SMPClientConfig -> Int -- | Default SMP client configuration. smpDefaultConfig :: SMPClientConfig -- | Type synonym for transmission from some SPM server queue. type SMPServerTransmission = (SMPServer, RecipientId, Command 'Broker) instance GHC.Exception.Type.Exception Simplex.Messaging.Client.SMPClientError instance GHC.Show.Show Simplex.Messaging.Client.SMPClientError instance GHC.Classes.Eq Simplex.Messaging.Client.SMPClientError module Simplex.Messaging.Agent.Store -- | Store class type. Defines store access methods for implementations. class Monad m => MonadAgentStore s m createRcvConn :: MonadAgentStore s m => s -> RcvQueue -> m () createSndConn :: MonadAgentStore s m => s -> SndQueue -> m () getConn :: MonadAgentStore s m => s -> ConnAlias -> m SomeConn getAllConnAliases :: MonadAgentStore s m => s -> m [ConnAlias] getRcvConn :: MonadAgentStore s m => s -> SMPServer -> RecipientId -> m SomeConn deleteConn :: MonadAgentStore s m => s -> ConnAlias -> m () upgradeRcvConnToDuplex :: MonadAgentStore s m => s -> ConnAlias -> SndQueue -> m () upgradeSndConnToDuplex :: MonadAgentStore s m => s -> ConnAlias -> RcvQueue -> m () setRcvQueueStatus :: MonadAgentStore s m => s -> RcvQueue -> QueueStatus -> m () setRcvQueueActive :: MonadAgentStore s m => s -> RcvQueue -> VerificationKey -> m () setSndQueueStatus :: MonadAgentStore s m => s -> SndQueue -> QueueStatus -> m () updateRcvIds :: MonadAgentStore s m => s -> RcvQueue -> m (InternalId, InternalRcvId, PrevExternalSndId, PrevRcvMsgHash) createRcvMsg :: MonadAgentStore s m => s -> RcvQueue -> RcvMsgData -> m () updateSndIds :: MonadAgentStore s m => s -> SndQueue -> m (InternalId, InternalSndId, PrevSndMsgHash) createSndMsg :: MonadAgentStore s m => s -> SndQueue -> SndMsgData -> m () getMsg :: MonadAgentStore s m => s -> ConnAlias -> InternalId -> m Msg -- | A receive queue. SMP queue through which the agent receives messages -- from a sender. data RcvQueue RcvQueue :: SMPServer -> RecipientId -> ConnAlias -> RecipientPrivateKey -> Maybe SenderId -> Maybe SenderPublicKey -> DecryptionKey -> Maybe VerificationKey -> QueueStatus -> RcvQueue [$sel:server:RcvQueue] :: RcvQueue -> SMPServer [$sel:rcvId:RcvQueue] :: RcvQueue -> RecipientId [$sel:connAlias:RcvQueue] :: RcvQueue -> ConnAlias [$sel:rcvPrivateKey:RcvQueue] :: RcvQueue -> RecipientPrivateKey [$sel:sndId:RcvQueue] :: RcvQueue -> Maybe SenderId [$sel:sndKey:RcvQueue] :: RcvQueue -> Maybe SenderPublicKey [$sel:decryptKey:RcvQueue] :: RcvQueue -> DecryptionKey [$sel:verifyKey:RcvQueue] :: RcvQueue -> Maybe VerificationKey [$sel:status:RcvQueue] :: RcvQueue -> QueueStatus -- | A send queue. SMP queue through which the agent sends messages to a -- recipient. data SndQueue SndQueue :: SMPServer -> SenderId -> ConnAlias -> SenderPrivateKey -> EncryptionKey -> SignatureKey -> QueueStatus -> SndQueue [$sel:server:SndQueue] :: SndQueue -> SMPServer [$sel:sndId:SndQueue] :: SndQueue -> SenderId [$sel:connAlias:SndQueue] :: SndQueue -> ConnAlias [$sel:sndPrivateKey:SndQueue] :: SndQueue -> SenderPrivateKey [$sel:encryptKey:SndQueue] :: SndQueue -> EncryptionKey [$sel:signKey:SndQueue] :: SndQueue -> SignatureKey [$sel:status:SndQueue] :: SndQueue -> QueueStatus -- | Type of a connection. data ConnType CRcv :: ConnType CSnd :: ConnType CDuplex :: ConnType -- | Connection of a specific type. -- -- data Connection (d :: ConnType) [RcvConnection] :: ConnAlias -> RcvQueue -> Connection CRcv [SndConnection] :: ConnAlias -> SndQueue -> Connection CSnd [DuplexConnection] :: ConnAlias -> RcvQueue -> SndQueue -> Connection CDuplex data SConnType :: ConnType -> Type [SCRcv] :: SConnType CRcv [SCSnd] :: SConnType CSnd [SCDuplex] :: SConnType CDuplex connType :: SConnType c -> ConnType -- | Connection of an unknown type. Used to refer to an arbitrary -- connection when retrieving from store. data SomeConn SomeConn :: SConnType d -> Connection d -> SomeConn type MsgHash = ByteString -- | Corresponds to last_external_snd_msg_id in -- connections table type PrevExternalSndId = Int64 -- | Corresponds to last_rcv_msg_hash in connections -- table type PrevRcvMsgHash = MsgHash -- | Corresponds to last_snd_msg_hash in connections -- table type PrevSndMsgHash = MsgHash data RcvMsgData RcvMsgData :: InternalId -> InternalRcvId -> InternalTs -> (ExternalSndId, ExternalSndTs) -> (BrokerId, BrokerTs) -> MsgBody -> MsgHash -> MsgHash -> MsgIntegrity -> RcvMsgData [$sel:internalId:RcvMsgData] :: RcvMsgData -> InternalId [$sel:internalRcvId:RcvMsgData] :: RcvMsgData -> InternalRcvId [$sel:internalTs:RcvMsgData] :: RcvMsgData -> InternalTs [$sel:senderMeta:RcvMsgData] :: RcvMsgData -> (ExternalSndId, ExternalSndTs) [$sel:brokerMeta:RcvMsgData] :: RcvMsgData -> (BrokerId, BrokerTs) [$sel:msgBody:RcvMsgData] :: RcvMsgData -> MsgBody [$sel:internalHash:RcvMsgData] :: RcvMsgData -> MsgHash [$sel:externalPrevSndHash:RcvMsgData] :: RcvMsgData -> MsgHash [$sel:msgIntegrity:RcvMsgData] :: RcvMsgData -> MsgIntegrity data SndMsgData SndMsgData :: InternalId -> InternalSndId -> InternalTs -> MsgBody -> MsgHash -> SndMsgData [$sel:internalId:SndMsgData] :: SndMsgData -> InternalId [$sel:internalSndId:SndMsgData] :: SndMsgData -> InternalSndId [$sel:internalTs:SndMsgData] :: SndMsgData -> InternalTs [$sel:msgBody:SndMsgData] :: SndMsgData -> MsgBody [$sel:internalHash:SndMsgData] :: SndMsgData -> MsgHash -- | A message in either direction that is stored by the agent. data Msg MRcv :: RcvMsg -> Msg MSnd :: SndMsg -> Msg -- | A message received by the agent from a sender. data RcvMsg RcvMsg :: MsgBase -> InternalRcvId -> ExternalSndId -> ExternalSndTs -> BrokerId -> BrokerTs -> RcvMsgStatus -> AckBrokerTs -> AckSenderTs -> MsgHash -> MsgIntegrity -> RcvMsg [$sel:msgBase:RcvMsg] :: RcvMsg -> MsgBase [$sel:internalRcvId:RcvMsg] :: RcvMsg -> InternalRcvId -- | Id of the message at sender, corresponds to -- $sel:internalSndId:SndMsgData from the sender's side. Sender Id -- is made sequential for detection of missing messages. For redundant / -- parallel queues, it also allows to keep track of duplicates and -- restore the original order before delivery to the client. [$sel:externalSndId:RcvMsg] :: RcvMsg -> ExternalSndId [$sel:externalSndTs:RcvMsg] :: RcvMsg -> ExternalSndTs -- | Id of the message at broker, although it is not sequential (to avoid -- metadata leakage for potential observer), it is needed to track -- repeated deliveries in case of connection loss - this logic is not -- implemented yet. [$sel:brokerId:RcvMsg] :: RcvMsg -> BrokerId [$sel:brokerTs:RcvMsg] :: RcvMsg -> BrokerTs [$sel:rcvMsgStatus:RcvMsg] :: RcvMsg -> RcvMsgStatus -- | Timestamp of acknowledgement to broker, corresponds to -- AcknowledgedToBroker status. Do not mix up with -- $sel:brokerTs:RcvMsg - timestamp created at broker after it -- receives the message from sender. [$sel:ackBrokerTs:RcvMsg] :: RcvMsg -> AckBrokerTs -- | Timestamp of acknowledgement to sender, corresponds to -- AcknowledgedToSender status. Do not mix up with -- $sel:externalSndTs:RcvMsg - timestamp created at sender before -- sending, which in its turn corresponds to -- $sel:internalTs:RcvMsgData in sending agent. [$sel:ackSenderTs:RcvMsg] :: RcvMsg -> AckSenderTs -- | Hash of previous message as received from sender - stored for -- integrity forensics. [$sel:externalPrevSndHash:RcvMsg] :: RcvMsg -> MsgHash [$sel:msgIntegrity:RcvMsg] :: RcvMsg -> MsgIntegrity newtype InternalRcvId InternalRcvId :: Int64 -> InternalRcvId [$sel:unRcvId:InternalRcvId] :: InternalRcvId -> Int64 type ExternalSndId = Int64 type ExternalSndTs = UTCTime type BrokerId = MsgId type BrokerTs = UTCTime data RcvMsgStatus Received :: RcvMsgStatus AcknowledgedToBroker :: RcvMsgStatus AcknowledgedToSender :: RcvMsgStatus type AckBrokerTs = UTCTime type AckSenderTs = UTCTime -- | A message sent by the agent to a recipient. data SndMsg SndMsg :: MsgBase -> InternalSndId -> SndMsgStatus -> SentTs -> DeliveredTs -> SndMsg [$sel:msgBase:SndMsg] :: SndMsg -> MsgBase -- | Id of the message sent / to be sent, as in its number in order of -- sending. [$sel:internalSndId:SndMsg] :: SndMsg -> InternalSndId [$sel:sndMsgStatus:SndMsg] :: SndMsg -> SndMsgStatus -- | Timestamp of the message received by broker, corresponds to -- Sent status. [$sel:sentTs:SndMsg] :: SndMsg -> SentTs -- | Timestamp of the message received by recipient, corresponds to -- Delivered status. [$sel:deliveredTs:SndMsg] :: SndMsg -> DeliveredTs newtype InternalSndId InternalSndId :: Int64 -> InternalSndId [$sel:unSndId:InternalSndId] :: InternalSndId -> Int64 data SndMsgStatus Created :: SndMsgStatus Sent :: SndMsgStatus Delivered :: SndMsgStatus type SentTs = UTCTime type DeliveredTs = UTCTime -- | Base message data independent of direction. data MsgBase MsgBase :: ConnAlias -> InternalId -> InternalTs -> MsgBody -> MsgHash -> MsgBase [$sel:connAlias:MsgBase] :: MsgBase -> ConnAlias -- | Monotonically increasing id of a message per connection, internal to -- the agent. Internal Id preserves ordering between both received and -- sent messages, and is needed to track the order of the conversation -- (which can be different for the sender / receiver) and address -- messages in commands. External [sender] Id cannot be used for this -- purpose due to a possibility of implementation errors in different -- agents. [$sel:internalId:MsgBase] :: MsgBase -> InternalId [$sel:internalTs:MsgBase] :: MsgBase -> InternalTs [$sel:msgBody:MsgBase] :: MsgBase -> MsgBody -- | Hash of the message as computed by agent. [$sel:internalHash:MsgBase] :: MsgBase -> MsgHash newtype InternalId InternalId :: Int64 -> InternalId [$sel:unId:InternalId] :: InternalId -> Int64 type InternalTs = UTCTime -- | Agent store error. data StoreError -- | IO exceptions in store actions. SEInternal :: ByteString -> StoreError -- | Connection alias not found (or both queues absent). SEConnNotFound :: StoreError -- | Connection alias already used. SEConnDuplicate :: StoreError -- | Wrong connection type, e.g. "send" connection when "receive" or -- "duplex" is expected, or vice versa. upgradeRcvConnToDuplex and -- upgradeSndConnToDuplex do not allow duplex connections - they -- would also return this error. SEBadConnType :: ConnType -> StoreError -- | Currently not used. The intention was to pass current expected queue -- status in methods, as we always know what it should be at any stage of -- the protocol, and in case it does not match use this error. SEBadQueueStatus :: StoreError -- | Used in getMsg that is not implemented/used. TODO remove. SENotImplemented :: StoreError instance GHC.Show.Show Simplex.Messaging.Agent.Store.RcvQueue instance GHC.Classes.Eq Simplex.Messaging.Agent.Store.RcvQueue instance GHC.Show.Show Simplex.Messaging.Agent.Store.SndQueue instance GHC.Classes.Eq Simplex.Messaging.Agent.Store.SndQueue instance GHC.Show.Show Simplex.Messaging.Agent.Store.ConnType instance GHC.Classes.Eq Simplex.Messaging.Agent.Store.ConnType instance GHC.Show.Show Simplex.Messaging.Agent.Store.InternalRcvId instance GHC.Classes.Eq Simplex.Messaging.Agent.Store.InternalRcvId instance GHC.Show.Show Simplex.Messaging.Agent.Store.RcvMsgStatus instance GHC.Classes.Eq Simplex.Messaging.Agent.Store.RcvMsgStatus instance GHC.Show.Show Simplex.Messaging.Agent.Store.InternalSndId instance GHC.Classes.Eq Simplex.Messaging.Agent.Store.InternalSndId instance GHC.Show.Show Simplex.Messaging.Agent.Store.SndMsgStatus instance GHC.Classes.Eq Simplex.Messaging.Agent.Store.SndMsgStatus instance GHC.Show.Show Simplex.Messaging.Agent.Store.InternalId instance GHC.Classes.Eq Simplex.Messaging.Agent.Store.InternalId instance GHC.Show.Show Simplex.Messaging.Agent.Store.MsgBase instance GHC.Classes.Eq Simplex.Messaging.Agent.Store.MsgBase instance GHC.Show.Show Simplex.Messaging.Agent.Store.SndMsg instance GHC.Classes.Eq Simplex.Messaging.Agent.Store.SndMsg instance GHC.Show.Show Simplex.Messaging.Agent.Store.RcvMsg instance GHC.Classes.Eq Simplex.Messaging.Agent.Store.RcvMsg instance GHC.Show.Show Simplex.Messaging.Agent.Store.Msg instance GHC.Classes.Eq Simplex.Messaging.Agent.Store.Msg instance GHC.Exception.Type.Exception Simplex.Messaging.Agent.Store.StoreError instance GHC.Show.Show Simplex.Messaging.Agent.Store.StoreError instance GHC.Classes.Eq Simplex.Messaging.Agent.Store.StoreError instance GHC.Classes.Eq (Simplex.Messaging.Agent.Store.Connection d) instance GHC.Show.Show (Simplex.Messaging.Agent.Store.Connection d) instance GHC.Classes.Eq (Simplex.Messaging.Agent.Store.SConnType d) instance GHC.Show.Show (Simplex.Messaging.Agent.Store.SConnType d) instance GHC.Show.Show Simplex.Messaging.Agent.Store.SomeConn instance GHC.Classes.Eq Simplex.Messaging.Agent.Store.SomeConn instance Data.Type.Equality.TestEquality Simplex.Messaging.Agent.Store.SConnType module Simplex.Messaging.Agent.Store.SQLite data SQLiteStore SQLiteStore :: FilePath -> Connection -> SQLiteStore [$sel:dbFilePath:SQLiteStore] :: SQLiteStore -> FilePath [$sel:dbConn:SQLiteStore] :: SQLiteStore -> Connection createSQLiteStore :: MonadUnliftIO m => FilePath -> m SQLiteStore connectSQLiteStore :: MonadUnliftIO m => FilePath -> m SQLiteStore instance (Control.Monad.IO.Unlift.MonadUnliftIO m, Control.Monad.Error.Class.MonadError Simplex.Messaging.Agent.Store.StoreError m) => Simplex.Messaging.Agent.Store.MonadAgentStore Simplex.Messaging.Agent.Store.SQLite.SQLiteStore m instance Database.SQLite.Simple.ToField.ToField Simplex.Messaging.Agent.Protocol.QueueStatus instance Database.SQLite.Simple.FromField.FromField Simplex.Messaging.Agent.Protocol.QueueStatus instance Database.SQLite.Simple.ToField.ToField Simplex.Messaging.Agent.Store.InternalRcvId instance Database.SQLite.Simple.FromField.FromField Simplex.Messaging.Agent.Store.InternalRcvId instance Database.SQLite.Simple.ToField.ToField Simplex.Messaging.Agent.Store.InternalSndId instance Database.SQLite.Simple.FromField.FromField Simplex.Messaging.Agent.Store.InternalSndId instance Database.SQLite.Simple.ToField.ToField Simplex.Messaging.Agent.Store.InternalId instance Database.SQLite.Simple.FromField.FromField Simplex.Messaging.Agent.Store.InternalId instance Database.SQLite.Simple.ToField.ToField Simplex.Messaging.Agent.Store.RcvMsgStatus instance Database.SQLite.Simple.ToField.ToField Simplex.Messaging.Agent.Store.SndMsgStatus instance Database.SQLite.Simple.ToField.ToField Simplex.Messaging.Agent.Protocol.MsgIntegrity instance Database.SQLite.Simple.FromField.FromField Simplex.Messaging.Agent.Protocol.MsgIntegrity instance (Database.SQLite.Simple.FromField.FromField a, Database.SQLite.Simple.FromField.FromField b, Database.SQLite.Simple.FromField.FromField c, Database.SQLite.Simple.FromField.FromField d, Database.SQLite.Simple.FromField.FromField e, Database.SQLite.Simple.FromField.FromField f, Database.SQLite.Simple.FromField.FromField g, Database.SQLite.Simple.FromField.FromField h, Database.SQLite.Simple.FromField.FromField i, Database.SQLite.Simple.FromField.FromField j, Database.SQLite.Simple.FromField.FromField k) => Database.SQLite.Simple.FromRow.FromRow (a, b, c, d, e, f, g, h, i, j, k) module Simplex.Messaging.Agent.Env.SQLite data AgentConfig AgentConfig :: ServiceName -> NonEmpty SMPServer -> Int -> Int -> Natural -> FilePath -> SMPClientConfig -> AgentConfig [$sel:tcpPort:AgentConfig] :: AgentConfig -> ServiceName [$sel:smpServers:AgentConfig] :: AgentConfig -> NonEmpty SMPServer [$sel:rsaKeySize:AgentConfig] :: AgentConfig -> Int [$sel:connIdBytes:AgentConfig] :: AgentConfig -> Int [$sel:tbqSize:AgentConfig] :: AgentConfig -> Natural [$sel:dbFile:AgentConfig] :: AgentConfig -> FilePath [$sel:smpCfg:AgentConfig] :: AgentConfig -> SMPClientConfig data Env Env :: AgentConfig -> TVar ChaChaDRG -> TVar Int -> Int -> TVar StdGen -> Env [$sel:config:Env] :: Env -> AgentConfig [$sel:idsDrg:Env] :: Env -> TVar ChaChaDRG [$sel:clientCounter:Env] :: Env -> TVar Int [$sel:reservedMsgSize:Env] :: Env -> Int [$sel:randomServer:Env] :: Env -> TVar StdGen newSMPAgentEnv :: (MonadUnliftIO m, MonadRandom m) => AgentConfig -> m Env module Simplex.Messaging.Agent.Client data AgentClient AgentClient :: TBQueue (ATransmission 'Client) -> TBQueue (ATransmission 'Agent) -> TBQueue SMPServerTransmission -> TVar (Map SMPServer SMPClient) -> TVar (Map SMPServer (Set ConnAlias)) -> TVar (Map ConnAlias SMPServer) -> Int -> AgentClient [$sel:rcvQ:AgentClient] :: AgentClient -> TBQueue (ATransmission 'Client) [$sel:sndQ:AgentClient] :: AgentClient -> TBQueue (ATransmission 'Agent) [$sel:msgQ:AgentClient] :: AgentClient -> TBQueue SMPServerTransmission [$sel:smpClients:AgentClient] :: AgentClient -> TVar (Map SMPServer SMPClient) [$sel:subscrSrvrs:AgentClient] :: AgentClient -> TVar (Map SMPServer (Set ConnAlias)) [$sel:subscrConns:AgentClient] :: AgentClient -> TVar (Map ConnAlias SMPServer) [$sel:clientId:AgentClient] :: AgentClient -> Int newAgentClient :: TVar Int -> AgentConfig -> STM AgentClient type AgentMonad m = (MonadUnliftIO m, MonadReader Env m, MonadError AgentErrorType m) getSMPServerClient :: forall m. AgentMonad m => AgentClient -> SMPServer -> m SMPClient closeSMPServerClients :: MonadUnliftIO m => AgentClient -> m () newReceiveQueue :: AgentMonad m => AgentClient -> SMPServer -> ConnAlias -> m (RcvQueue, SMPQueueInfo) subscribeQueue :: AgentMonad m => AgentClient -> RcvQueue -> ConnAlias -> m () sendConfirmation :: forall m. AgentMonad m => AgentClient -> SndQueue -> SenderPublicKey -> m () sendHello :: forall m. AgentMonad m => AgentClient -> SndQueue -> VerificationKey -> m () secureQueue :: AgentMonad m => AgentClient -> RcvQueue -> SenderPublicKey -> m () sendAgentMessage :: AgentMonad m => AgentClient -> SndQueue -> ByteString -> m () decryptAndVerify :: AgentMonad m => RcvQueue -> ByteString -> m ByteString verifyMessage :: AgentMonad m => Maybe VerificationKey -> ByteString -> m ByteString sendAck :: AgentMonad m => AgentClient -> RcvQueue -> m () suspendQueue :: AgentMonad m => AgentClient -> RcvQueue -> m () deleteQueue :: AgentMonad m => AgentClient -> RcvQueue -> m () logServer :: AgentMonad m => ByteString -> AgentClient -> SMPServer -> QueueId -> ByteString -> m () removeSubscription :: AgentMonad m => AgentClient -> ConnAlias -> m () cryptoError :: CryptoError -> AgentErrorType -- | This module defines SMP protocol agent with SQLite persistence. -- -- See -- https://github.com/simplex-chat/simplexmq/blob/master/protocol/agent-protocol.md module Simplex.Messaging.Agent -- | Runs an SMP agent as a TCP service using passed configuration. -- -- See a full agent executable here: -- https://github.com/simplex-chat/simplexmq/blob/master/apps/smp-agent/Main.hs runSMPAgent :: (MonadRandom m, MonadUnliftIO m) => ATransport -> AgentConfig -> m () -- | Runs an SMP agent as a TCP service using passed configuration with -- signalling. -- -- This function uses passed TMVar to signal when the server is ready to -- accept TCP requests (True) and when it is disconnected from the TCP -- socket once the server thread is killed (False). runSMPAgentBlocking :: (MonadRandom m, MonadUnliftIO m) => ATransport -> TMVar Bool -> AgentConfig -> m () -- | Creates an SMP agent instance that receives commands and sends -- responses via TBQueues. getSMPAgentClient :: (MonadUnliftIO m, MonadReader Env m) => m AgentClient -- | Runs an SMP agent instance that receives commands and sends responses -- via TBQueues. runSMPAgentClient :: (MonadUnliftIO m, MonadReader Env m) => AgentClient -> m ()