diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cd989e5a..e17de756c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,27 @@ +# 0.4.0 + +- SMP server implementation and [SMP protocol](https://github.com/simplex-chat/simplexmq/blob/master/protocol/simplex-messaging.md) changes: + - support 3072 bit RSA key size + - add SMP queue quotas + - set default transport block size to 4096 bits + - allow SMP client to change transport block size during transport connection handshake +- SMP agent implementation and protocol changes: + - additional connection confirmation step for initiating party + - automatically resume subscribed duplex connections once transport connection is resumed + - passing an arbitrary binary information between parties during the duplex connection handshake - can be used to identify parties + - asynchronous duplex connection handshake - the parties do not have to be online at the same time + - asynchronous message delivery - the agent does not need transport connection to accept client messages for delivery + - additional confirmation of message reception from the client to prevent message loss in case of process termination + - set transport block size to 8192 bits (in the future the agent protocol can allow to have different block sizes for different duplex connections) + - added client commands and notifications (see [agent protocol](https://github.com/simplex-chat/simplexmq/blob/master/protocol/agent-protocol.md)): + - `REQ` - the notification about joining party establishing connection + - `ACPT` - the command to accept connection with the joining party + - `INFO` - the notification with the information from the initiating party + - `DOWN`/`UP` - the notifications about losing/resuming the connection + - `ACK` - the command to confirm that the message reception/processing is complete + - `MID` - the response to `SEND` confirming that the message is accepted by the agent + - `MERR` - the notification about permanent message delivery error (e.g., `ERR AUTH` indicating that the queue was removed) + # 0.3.2 - Support websockets diff --git a/src/Simplex/Messaging/Agent/Protocol.hs b/src/Simplex/Messaging/Agent/Protocol.hs index 518b4219d..44e42cdd4 100644 --- a/src/Simplex/Messaging/Agent/Protocol.hs +++ b/src/Simplex/Messaging/Agent/Protocol.hs @@ -312,7 +312,7 @@ data SMPServer = SMPServer deriving (Eq, Ord, Show) instance IsString SMPServer where - fromString = parseString . parseAll $ smpServerP + fromString = parseString $ parseAll smpServerP -- | SMP agent connection alias. type ConnId = ByteString diff --git a/src/Simplex/Messaging/Crypto.hs b/src/Simplex/Messaging/Crypto.hs index 10e7ad5b5..ccd8f5f90 100644 --- a/src/Simplex/Messaging/Crypto.hs +++ b/src/Simplex/Messaging/Crypto.hs @@ -169,10 +169,10 @@ instance PrivateKey APrivateKey where else Just $ PublicKey k instance IsString FullPrivateKey where - fromString = parseString (decode >=> decodePrivKey) + fromString = parseString $ decode >=> decodePrivKey instance IsString PublicKey where - fromString = parseString (decode >=> decodePubKey) + fromString = parseString $ decode >=> decodePubKey instance ToField SafePrivateKey where toField = toField . encodePrivKey diff --git a/src/Simplex/Messaging/Transport.hs b/src/Simplex/Messaging/Transport.hs index d8869f436..83d353ec9 100644 --- a/src/Simplex/Messaging/Transport.hs +++ b/src/Simplex/Messaging/Transport.hs @@ -66,6 +66,7 @@ import Data.Functor (($>)) import Data.Maybe(fromMaybe) import Data.Set (Set) import qualified Data.Set as S +import Data.String import Data.Word (Word32) import GHC.Generics (Generic) import GHC.IO.Exception (IOErrorType (..)) @@ -74,7 +75,7 @@ import Generic.Random (genericArbitraryU) import Network.Socket import Network.Transport.Internal (decodeNum16, decodeNum32, encodeEnum16, encodeEnum32, encodeWord32) import qualified Simplex.Messaging.Crypto as C -import Simplex.Messaging.Parsers (parse, parseAll, parseRead1) +import Simplex.Messaging.Parsers (parse, parseAll, parseRead1, parseString) import Simplex.Messaging.Util (bshow, liftError) import System.IO import System.IO.Error @@ -213,11 +214,14 @@ trimCR s = if B.last s == '\r' then B.init s else s data SMPVersion = SMPVersion Int Int Int Int deriving (Eq, Ord) +instance IsString SMPVersion where + fromString = parseString $ parseAll smpVersionP + major :: SMPVersion -> (Int, Int) major (SMPVersion a b _ _) = (a, b) currentSMPVersion :: SMPVersion -currentSMPVersion = SMPVersion 0 3 2 0 +currentSMPVersion = "0.4.0.0" serializeSMPVersion :: SMPVersion -> ByteString serializeSMPVersion (SMPVersion a b c d) = B.intercalate "." [bshow a, bshow b, bshow c, bshow d] diff --git a/tests/AgentTests.hs b/tests/AgentTests.hs index 545bcece4..73dd732c2 100644 --- a/tests/AgentTests.hs +++ b/tests/AgentTests.hs @@ -108,10 +108,10 @@ testDuplexConnection _ alice bob = do alice <# ("", "bob", CON) alice #: ("3", "bob", "SEND :hello") #> ("3", "bob", MID 1) alice <# ("", "bob", SENT 1) - alice #: ("4", "bob", "SEND :how are you?") #> ("4", "bob", MID 2) - alice <# ("", "bob", SENT 2) bob <#= \case ("", "alice", Msg "hello") -> True; _ -> False bob #: ("12", "alice", "ACK 1") #> ("12", "alice", OK) + alice #: ("4", "bob", "SEND :how are you?") #> ("4", "bob", MID 2) + alice <# ("", "bob", SENT 2) bob <#= \case ("", "alice", Msg "how are you?") -> True; _ -> False bob #: ("13", "alice", "ACK 2") #> ("13", "alice", OK) bob #: ("14", "alice", "SEND 9\nhello too") #> ("14", "alice", MID 3) @@ -141,10 +141,10 @@ testDuplexConnRandomIds _ alice bob = do alice <# ("", bobConn, CON) alice #: ("2", bobConn, "SEND :hello") #> ("2", bobConn, MID 1) alice <# ("", bobConn, SENT 1) - alice #: ("3", bobConn, "SEND :how are you?") #> ("3", bobConn, MID 2) - alice <# ("", bobConn, SENT 2) bob <#= \case ("", c, Msg "hello") -> c == aliceConn; _ -> False bob #: ("12", aliceConn, "ACK 1") #> ("12", aliceConn, OK) + alice #: ("3", bobConn, "SEND :how are you?") #> ("3", bobConn, MID 2) + alice <# ("", bobConn, SENT 2) bob <#= \case ("", c, Msg "how are you?") -> c == aliceConn; _ -> False bob #: ("13", aliceConn, "ACK 2") #> ("13", aliceConn, OK) bob #: ("14", aliceConn, "SEND 9\nhello too") #> ("14", aliceConn, MID 3) @@ -166,10 +166,10 @@ testSubscription _ alice1 alice2 bob = do (alice1, "alice") `connect` (bob, "bob") bob #: ("12", "alice", "SEND 5\nhello") #> ("12", "alice", MID 1) bob <# ("", "alice", SENT 1) - bob #: ("13", "alice", "SEND 11\nhello again") #> ("13", "alice", MID 2) - bob <# ("", "alice", SENT 2) alice1 <#= \case ("", "bob", Msg "hello") -> True; _ -> False alice1 #: ("1", "bob", "ACK 1") #> ("1", "bob", OK) + bob #: ("13", "alice", "SEND 11\nhello again") #> ("13", "alice", MID 2) + bob <# ("", "alice", SENT 2) alice1 <#= \case ("", "bob", Msg "hello again") -> True; _ -> False alice1 #: ("2", "bob", "ACK 2") #> ("2", "bob", OK) alice2 #: ("21", "bob", "SUB") #> ("21", "bob", OK)