{-# OPTIONS_HADDOCK not-home #-}
module MagicWormhole.Internal.Versions
( versionExchange
, Versions(..)
, VersionsError(..)
) where
import Protolude hiding (phase)
import Data.Aeson (FromJSON, ToJSON, (.=), object, Value(..), (.:))
import Data.Aeson.Types (typeMismatch)
import qualified Data.Aeson as Aeson
import Data.String (String)
import qualified MagicWormhole.Internal.ClientProtocol as ClientProtocol
import qualified MagicWormhole.Internal.Messages as Messages
versionExchange
:: ClientProtocol.Connection
-> ClientProtocol.SessionKey
-> IO Versions
versionExchange conn key = do
(_, theirVersions) <- concurrently sendVersion (atomically receiveVersion)
if theirVersions /= Versions then throwIO VersionMismatch else pure Versions
where
sendVersion = ClientProtocol.sendEncrypted conn key Messages.VersionPhase (ClientProtocol.PlainText (toS (Aeson.encode Versions)))
receiveVersion = do
(phase, ClientProtocol.PlainText plaintext) <- ClientProtocol.receiveEncrypted conn key
unless (phase == Messages.VersionPhase) retry
either (throwSTM . ParseError) pure $ Aeson.eitherDecode (toS plaintext)
data Versions = Versions deriving (Eq, Show)
instance ToJSON Versions where
toJSON _ = object ["app_versions" .= object []]
instance FromJSON Versions where
parseJSON (Object v) = do
(Object _versions) <- v .: "app_versions"
pure Versions
parseJSON unknown = typeMismatch "Versions" unknown
data VersionsError
= ParseError String
| VersionMismatch
deriving (Eq, Show, Typeable)
instance Exception VersionsError