put smp errors into proxy wrappers (#1103)

* put smp errors into proxy wrappers

* use substring in PROXY UNEXPECTED error

* fix encoding

* revert String encoding, discard invalid errors in QC

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
This commit is contained in:
Alexander BondarenkoandEvgeny Poberezkin authored and GitHub committed 2024-04-19 14:58:15 +01:00
1 parent 7712070cb3
commit 58ede38bf4
5 files changed
+54 -32

No files matched your search

+35 -19
View File
@@ -195,6 +195,8 @@ import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.List.NonEmpty as L
import Data.Maybe (isJust, isNothing)
import Data.String
import qualified Data.Text as T
import Data.Text.Encoding (encodeUtf8)
import Data.Time.Clock.System (SystemTime (..))
import Data.Type.Equality
import Data.Word (Word16)
@@ -210,7 +212,7 @@ import Simplex.Messaging.Parsers
import Simplex.Messaging.ServiceScheme
import Simplex.Messaging.Transport
import Simplex.Messaging.Transport.Client (TransportHost, TransportHosts (..))
import Simplex.Messaging.Util (bshow, eitherToMaybe, (<$?>))
import Simplex.Messaging.Util (bshow, eitherToMaybe, safeDecodeUtf8, (<$?>))
import Simplex.Messaging.Version
import Simplex.Messaging.Version.Internal
@@ -1167,11 +1169,11 @@ data ErrorType
instance StrEncoding ErrorType where
strEncode = \case
CMD e -> "CMD " <> bshow e
PROXY e -> "PROXY " <> bshow e
PROXY e -> "PROXY " <> strEncode e
e -> bshow e
strP =
"CMD " *> (CMD <$> parseRead1)
<|> "PROXY " *> (PROXY <$> parseRead1)
<|> "PROXY " *> (PROXY <$> strP)
<|> parseRead1
-- | SMP command error type.
@@ -1190,20 +1192,19 @@ data CommandError
NO_ENTITY
deriving (Eq, Read, Show)
-- TODO keep error params
data ProxyError
= -- | Correctly parsed SMP server ERR response.
-- This error is forwarded to the agent client as `ERR SMP err`.
PROTOCOL -- {protocolErr :: String}
PROTOCOL {protocolErr :: ErrorType}
| -- | Invalid server response that failed to parse.
-- Forwarded to the agent client as `ERR BROKER RESPONSE`.
RESPONSE -- {responseErr :: String}
| UNEXPECTED
RESPONSE {responseErr :: ErrorType}
| UNEXPECTED {unexpectedResponse :: String} -- 'String' for using derived JSON and Arbitrary instances
| TIMEOUT
| NETWORK
| BAD_HOST
| NO_SESSION
| TRANSPORT -- {transportErr :: TransportError}
| TRANSPORT {transportErr :: TransportError}
deriving (Eq, Read, Show)
-- | SMP transmission parser.
@@ -1473,26 +1474,42 @@ instance Encoding CommandError where
instance Encoding ProxyError where
smpEncode e = case e of
PROTOCOL -> "PROTOCOL"
RESPONSE -> "RESPONSE"
UNEXPECTED -> "UNEXPECTED"
PROTOCOL et -> "PROTOCOL " <> smpEncode et
RESPONSE et -> "RESPONSE " <> smpEncode et
UNEXPECTED s -> "UNEXPECTED " <> smpEncode (encodeUtf8 $ T.pack s)
TIMEOUT -> "TIMEOUT"
NETWORK -> "NETWORK"
BAD_HOST -> "BAD_HOST"
NO_SESSION -> "NO_SESSION"
TRANSPORT -> "TRANSPORT"
TRANSPORT t -> "TRANSPORT " <> serializeTransportError t
smpP =
A.takeTill (== ' ') >>= \case
"PROTOCOL" -> pure PROTOCOL
"RESPONSE" -> pure RESPONSE
"UNEXPECTED" -> pure UNEXPECTED
"PROTOCOL" -> PROTOCOL <$> _smpP
"RESPONSE" -> RESPONSE <$> _smpP
"UNEXPECTED" -> UNEXPECTED . (T.unpack . safeDecodeUtf8) <$> _smpP
"TIMEOUT" -> pure TIMEOUT
"NETWORK" -> pure NETWORK
"BAD_HOST" -> pure BAD_HOST
"NO_SESSION" -> pure NO_SESSION
"TRANSPORT" -> pure TRANSPORT
"TRANSPORT" -> TRANSPORT <$> (A.space *> transportErrorP)
_ -> fail "bad command error type"
instance StrEncoding ProxyError where
strEncode = \case
PROTOCOL et -> "PROTOCOL " <> strEncode et
RESPONSE et -> "RESPONSE " <> strEncode et
UNEXPECTED "" -> "UNEXPECTED" -- Arbitrary instance generates empty strings which String instance can't handle
UNEXPECTED s -> "UNEXPECTED " <> strEncode s
TRANSPORT t -> "TRANSPORT " <> serializeTransportError t
e -> bshow e
strP =
"PROTOCOL " *> (PROTOCOL <$> strP)
<|> "RESPONSE " *> (RESPONSE <$> strP)
<|> "UNEXPECTED " *> (UNEXPECTED <$> strP)
<|> "UNEXPECTED" $> UNEXPECTED ""
<|> "TRANSPORT " *> (TRANSPORT <$> transportErrorP)
<|> parseRead1
-- | Send signed SMP transmission to TCP transport.
tPut :: Transport c => THandle v c p -> NonEmpty (Either TransportError SentRawTransmission) -> IO [Either TransportError ()]
tPut th@THandle {params} = fmap concat . mapM tPutBatch . batchTransmissions (batch params) (blockSize params)
@@ -1630,6 +1647,5 @@ $(J.deriveJSON defaultJSON ''MsgFlags)
$(J.deriveJSON (sumTypeJSON id) ''CommandError)
$(J.deriveJSON (sumTypeJSON id) ''ProxyError)
$(J.deriveJSON (sumTypeJSON id) ''ErrorType)
-- run deriveJSON in one TH splice to allow mutual instance
$(concat <$> mapM @[] (J.deriveJSON (sumTypeJSON id)) [''ProxyError, ''ErrorType])