Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var __viteBrowserExternal = {};

export { __viteBrowserExternal as default };
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const __viteBrowserExternal = {};

export { __viteBrowserExternal as default };
7 changes: 2 additions & 5 deletions apps/xftp-server/static/xftp-web-bundle/crypto.worker.js

Large diffs are not rendered by default.

26 changes: 20 additions & 6 deletions apps/xftp-server/static/xftp-web-bundle/index.js

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions simplexmq.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ extra-source-files:
apps/common/Web/static/media/testflight.png
apps/xftp-server/static/media/xftp-protocol.svg
apps/xftp-server/static/media/xftp-protocol-dark.svg
apps/xftp-server/static/xftp-web-bundle/__vite-browser-external-C6dvzdW7.js
apps/xftp-server/static/xftp-web-bundle/__vite-browser-external.js
apps/xftp-server/static/xftp-web-bundle/crypto.worker.js
apps/xftp-server/static/xftp-web-bundle/index.css
apps/xftp-server/static/xftp-web-bundle/index.js
Expand Down
5 changes: 3 additions & 2 deletions src/Simplex/FileTransfer/Client/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import Simplex.Messaging.Encoding
import Simplex.Messaging.Encoding.String (StrEncoding (..))
import Simplex.Messaging.Parsers (parseAll)
import Simplex.Messaging.Protocol (ProtoServerWithAuth (..), ProtocolServer (..), SenderId, SndPrivateAuthKey, XFTPServer, XFTPServerWithAuth)
import Simplex.Messaging.ServiceScheme (SrvLoc (..))
import Simplex.Messaging.Util (groupAllOn, ifM, tshow, whenM)
import System.Exit (exitFailure)
import System.FilePath (splitFileName, (</>))
Expand Down Expand Up @@ -609,9 +610,9 @@ decodeWebURI fragment = do
strDecode yaml >>= validateFileDescription

-- | Extract web link host and URI fragment from a file description.
-- Returns (hostname, uriFragment) for https://hostname/#uriFragment.
-- Returns (authority, uriFragment) for https://authority/#uriFragment.
fileWebLink :: FileDescription 'FRecipient -> Maybe (B.ByteString, B.ByteString)
fileWebLink fd@FileDescription {chunks} = case chunks of
(FileChunk {replicas = FileChunkReplica {server = ProtocolServer {host}} : _} : _) ->
Just (strEncode (L.head host), encodeWebURI fd)
Just (strEncode (SrvLoc (L.head host) ""), encodeWebURI fd)
_ -> Nothing
2 changes: 1 addition & 1 deletion src/Simplex/Messaging/Agent/Protocol.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1608,7 +1608,7 @@ instance ConnectionModeI m => StrEncoding (ConnShortLink m) where
where
(authority, paramHosts) = case sch of
SLSSimplex -> ("simplex:", h : hs)
SLSServer -> ("https://" <> strEncode h, hs)
SLSServer -> ("https://" <> strEncode (SrvLoc h ""), hs)
lnkIdStr = if B.null lnkId then "" else B64.encodeUnpadded lnkId <> "/"
queryStr = if B.null query then "" else "?" <> query
query =
Expand Down
11 changes: 6 additions & 5 deletions src/Simplex/Messaging/Protocol.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1308,7 +1308,7 @@ instance ProtocolTypeI p => Encoding (ProtocolServer p) where

instance ProtocolTypeI p => StrEncoding (ProtocolServer p) where
strEncode ProtocolServer {scheme, host, port, keyHash} =
strEncodeServer scheme (strEncode host) port keyHash Nothing
strEncodeServer scheme host port keyHash Nothing
strP =
serverStrP >>= \case
(AProtocolServer _ srv, Nothing) -> either fail pure $ checkProtocolType srv
Expand Down Expand Up @@ -1353,7 +1353,7 @@ deriving instance Show AProtoServerWithAuth

instance ProtocolTypeI p => StrEncoding (ProtoServerWithAuth p) where
strEncode (ProtoServerWithAuth ProtocolServer {scheme, host, port, keyHash} auth_) =
strEncodeServer scheme (strEncode host) port keyHash auth_
strEncodeServer scheme host port keyHash auth_
strP = (\(AProtoServerWithAuth _ srv) -> checkProtocolType srv) <$?> strP

instance StrEncoding AProtoServerWithAuth where
Expand Down Expand Up @@ -1390,12 +1390,13 @@ legacyServerP = do

legacyStrEncodeServer :: ProtocolTypeI p => ProtocolServer p -> ByteString
legacyStrEncodeServer ProtocolServer {scheme, host, port, keyHash} =
strEncodeServer scheme (strEncode $ L.head host) port keyHash Nothing
strEncodeServer scheme [L.head host] port keyHash Nothing

strEncodeServer :: ProtocolTypeI p => SProtocolType p -> ByteString -> ServiceName -> C.KeyHash -> Maybe BasicAuth -> ByteString
strEncodeServer :: ProtocolTypeI p => SProtocolType p -> NonEmpty TransportHost -> ServiceName -> C.KeyHash -> Maybe BasicAuth -> ByteString
strEncodeServer scheme host port keyHash auth_ =
strEncode scheme <> "://" <> strEncode keyHash <> maybe "" ((":" <>) . strEncode) auth_ <> "@" <> host <> portStr
strEncode scheme <> "://" <> strEncode keyHash <> maybe "" ((":" <>) . strEncode) auth_ <> "@" <> hostStr <> portStr
where
hostStr = B.intercalate "," $ map (strEncode . (`SrvLoc` "")) $ L.toList host
portStr = B.pack $ if null port then "" else ':' : port

serverStrP :: Parser (AProtocolServer, Maybe BasicAuth)
Expand Down
2 changes: 1 addition & 1 deletion src/Simplex/Messaging/ServiceScheme.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ data SrvLoc = SrvLoc TransportHost ServiceName

instance StrEncoding SrvLoc where
strEncode (SrvLoc host port)
| null port = strEncode host
| null port = h
| otherwise = h <> B.pack (':' : port)
where
h = case host of
Expand Down
3 changes: 2 additions & 1 deletion src/Simplex/RemoteControl/Invitation.hs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import qualified Simplex.Messaging.Crypto as C
import Simplex.Messaging.Encoding
import Simplex.Messaging.Encoding.String
import Simplex.Messaging.Parsers (parseAll)
import Simplex.Messaging.ServiceScheme (SrvLoc (..))
import Simplex.Messaging.Transport.Client (TransportHost)
import Simplex.RemoteControl.Types (VersionRangeRCP)

Expand Down Expand Up @@ -61,7 +62,7 @@ instance StrEncoding RCInvitation where
[ "xrcp:/",
strEncode ca,
"@",
strEncode host,
strEncode (SrvLoc host ""),
":",
strEncode port,
"#/?",
Expand Down
16 changes: 16 additions & 0 deletions tests/AgentTests/ConnectionRequestTests.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module AgentTests.ConnectionRequestTests
) where

import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import Network.HTTP.Types (urlEncode)
import Simplex.Messaging.Agent.Protocol
import qualified Simplex.Messaging.Crypto as C
Expand All @@ -27,6 +28,7 @@ import Simplex.Messaging.Encoding
import Simplex.Messaging.Encoding.String
import Simplex.Messaging.Protocol (EntityId (..), ProtocolServer (..), QueueMode (..), currentSMPClientVersion, supportedSMPClientVRange, pattern VersionSMPC)
import Simplex.Messaging.ServiceScheme (ServiceScheme (..))
import Simplex.Messaging.Transport.Client (TransportHost)
import Simplex.Messaging.Version
import Test.Hspec hiding (fit, it)
import Util
Expand Down Expand Up @@ -276,6 +278,11 @@ connectionRequestTests =
contactAddressV2 #== ("https://simplex.chat/contact#/?v=1-2&smp=" <> url queueStr) -- adjusted to v2
contactAddressV2 #== ("https://simplex.chat/contact#/?v=2-2&smp=" <> url queueStr)
contactAddressClientData #==# ("simplex:/contact#/?v=2-7&smp=" <> url queueStr <> "&data=" <> url "{\"type\":\"group_link\", \"group_link_id\":\"abc\"}")
it "should generate a bracketed IPv6 application-server authority" $ do
let ipv6Host = either error id (strDecode "2001:db8::1") :: TransportHost
request = CRInvitationUri (connReqData {crScheme = SSAppServer $ SrvLoc ipv6Host ""}) testE2ERatchetParams
encoded = strEncode request
encoded `shouldSatisfy` B.isPrefixOf "https://[2001:db8::1]/invitation#/?"
it "should serialize / parse queue address, connection invitations and contact addresses as binary" $ do
smpEncodingTest queue
smpEncodingTest queueNoQM -- this passes, no queue mode patch in SMPQueueUri encoding
Expand Down Expand Up @@ -303,6 +310,11 @@ connectionRequestTests =
smpEncodingTest contactAddressV2
smpEncodingTest contactAddressClientData
it "should serialize / parse short links" $ do
let ipv6Host = either error id (strDecode "2001:db8::1") :: TransportHost
ipv6Srv = srv {host = [ipv6Host, "jjbyvoemxysm7qxap7m5d5m35jzv5qq6gnlv7s4rsn7tdwwmuqciwpid.onion"]}
linkKey = LinkKey "0123456789abcdef0123456789abcdef"
ipv6Contact = CSLContact SLSServer CCTContact ipv6Srv linkKey
ipv6Invitation = CSLInvitation SLSServer ipv6Srv (EntityId "0123456789abcdef01234567") linkKey
CSLContact SLSServer CCTContact srv (LinkKey "0123456789abcdef0123456789abcdef") #==# "https://smp.simplex.im/a#MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY?h=jjbyvoemxysm7qxap7m5d5m35jzv5qq6gnlv7s4rsn7tdwwmuqciwpid.onion&p=5223&c=1234-w"
CSLContact SLSServer CCTGroup srv (LinkKey "0123456789abcdef0123456789abcdef") #==# "https://smp.simplex.im/g#MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY?h=jjbyvoemxysm7qxap7m5d5m35jzv5qq6gnlv7s4rsn7tdwwmuqciwpid.onion&p=5223&c=1234-w"
CSLContact SLSServer CCTContact shortSrv (LinkKey "0123456789abcdef0123456789abcdef") #==# "https://smp.simplex.im/a#MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY"
Expand All @@ -313,6 +325,10 @@ connectionRequestTests =
CSLContact SLSSimplex CCTContact shortSrv (LinkKey "0123456789abcdef0123456789abcdef") #==# "simplex:/a#MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY?h=smp.simplex.im"
CSLInvitation SLSSimplex srv (EntityId "0123456789abcdef01234567") (LinkKey "0123456789abcdef0123456789abcdef") #==# "simplex:/i#MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3/MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY?h=smp.simplex.im%2Cjjbyvoemxysm7qxap7m5d5m35jzv5qq6gnlv7s4rsn7tdwwmuqciwpid.onion&p=5223&c=1234-w"
CSLInvitation SLSSimplex shortSrv (EntityId "0123456789abcdef01234567") (LinkKey "0123456789abcdef0123456789abcdef") #==# "simplex:/i#MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3/MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY?h=smp.simplex.im"
ipv6Contact #==# "https://[2001:db8::1]/a#MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY?h=jjbyvoemxysm7qxap7m5d5m35jzv5qq6gnlv7s4rsn7tdwwmuqciwpid.onion&p=5223&c=1234-w"
ipv6Invitation #==# "https://[2001:db8::1]/i#MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3/MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY?h=jjbyvoemxysm7qxap7m5d5m35jzv5qq6gnlv7s4rsn7tdwwmuqciwpid.onion&p=5223&c=1234-w"
smpEncodingTest ipv6Contact
smpEncodingTest ipv6Invitation
it "should shorten / restore short links" $ do
let contact = CSLContact SLSServer CCTContact
shortenShortLink [srv] (contact srv (LinkKey "0123456789abcdef0123456789abcdef"))
Expand Down
42 changes: 35 additions & 7 deletions tests/CoreTests/EncodingTests.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import Data.Time.ISO8601 (parseISO8601)
import Simplex.Messaging.Encoding
import Simplex.Messaging.Encoding.String
import Simplex.Messaging.Parsers (parseAll)
import Simplex.Messaging.Protocol (ProtocolServer (..), XFTPServer)
import Simplex.Messaging.Protocol (NtfServer, ProtoServerWithAuth (..), ProtocolServer (..), SMPServer, XFTPServer, legacyStrEncodeServer)
import Simplex.Messaging.ServiceScheme (ServiceScheme (..), SrvLoc (..))
import Simplex.Messaging.Transport.Client (TransportHost (..))
import Test.Hspec hiding (fit, it)
Expand Down Expand Up @@ -74,6 +74,8 @@ encodingTests = modifyMaxSuccess (const 1000) $ do
shouldReject @TransportHost "[simplex.chat]"
shouldReject @TransportHost "[smp.simplex.im]"
describe "Encoding service locations" $ do
it "should encode and decode bracketed IPv6 host with implicit HTTPS port" $
(SSAppServer $ SrvLoc ipv6Host "") #==# "https://[2001:db8::1]"
it "should parse bracketed IPv6 host with port" $ do
strDecode @ServiceScheme "https://[2001:db8::1]:8443"
`shouldBe` Right (SSAppServer $ SrvLoc "2001:db8::1" "8443")
Expand All @@ -82,12 +84,38 @@ encodingTests = modifyMaxSuccess (const 1000) $ do
it "should reject bracketed non-IPv6 host" $
shouldReject @ServiceScheme "https://[simplex.chat]:8443"
describe "Encoding protocol servers" $ do
it "should parse bracketed IPv6 server host with port" $
case strDecode @XFTPServer "xftp://1234-w==@[2001:db8::1]:443" of
Left err -> expectationFailure err
Right (ProtocolServer _ parsedHost parsedPort _) -> do
parsedHost `shouldBe` (ipv6Host :| [])
parsedPort `shouldBe` "443"
it "should canonically round-trip IPv6 server hosts and ports" $ do
let xftp = either error id (strDecode "xftp://1234-w==@example.com:5223") :: XFTPServer
ipv6Server = xftp {host = ipv6Host :| [], port = "5223"}
defaultPortServer = ipv6Server {port = ""}
ipv6First = ipv6Server {host = ipv6Host :| ["example.com"]}
ipv6Last = ipv6Server {host = "example.com" :| [ipv6Host]}
ipv6Server #==# "xftp://1234-w==@[2001:db8::1]:5223"
defaultPortServer #==# "xftp://1234-w==@[2001:db8::1]"
ipv6First #==# "xftp://1234-w==@[2001:db8::1],example.com:5223"
ipv6Last #==# "xftp://1234-w==@example.com,[2001:db8::1]:5223"
ipv6First {port = ""} #==# "xftp://1234-w==@[2001:db8::1],example.com"
ipv6Last {port = ""} #==# "xftp://1234-w==@example.com,[2001:db8::1]"
it "should bracket IPv6 for each protocol and authenticated and legacy encoders" $ do
let smp = (either error id (strDecode "smp://1234-w==@example.com:5223") :: SMPServer) {host = ipv6Host :| []}
ntf = (either error id (strDecode "ntf://1234-w==@example.com:5223") :: NtfServer) {host = ipv6Host :| []}
xftp = (either error id (strDecode "xftp://1234-w==@example.com:5223") :: XFTPServer) {host = ipv6Host :| ["example.com"]}
strEncode smp `shouldBe` "smp://1234-w==@[2001:db8::1]:5223"
strDecode (strEncode smp) `shouldBe` Right smp
strEncode ntf `shouldBe` "ntf://1234-w==@[2001:db8::1]:5223"
strDecode (strEncode ntf) `shouldBe` Right ntf
let authenticated = ProtoServerWithAuth xftp (Just "user")
legacy = legacyStrEncodeServer xftp
strEncode authenticated `shouldBe` "xftp://1234-w==:user@[2001:db8::1],example.com:5223"
strDecode (strEncode authenticated) `shouldBe` Right authenticated
legacy `shouldBe` "xftp://1234-w==@[2001:db8::1]:5223"
strDecode legacy `shouldBe` Right xftp {host = ipv6Host :| []}
it "should preserve non-IPv6 server encodings" $ do
let xftp = either error id (strDecode "xftp://1234-w==@example.com:5223") :: XFTPServer
strEncode xftp {host = THIPv4 (192, 0, 2, 1) :| []} `shouldBe` "xftp://1234-w==@192.0.2.1:5223"
strEncode xftp `shouldBe` "xftp://1234-w==@example.com:5223"
strEncode xftp {host = "beccx4yfxxbvyhqypaavemqurytl6hozr47wfc7uuecacjqdvwpw2xid.onion" :| []}
`shouldBe` "xftp://1234-w==@beccx4yfxxbvyhqypaavemqurytl6hozr47wfc7uuecacjqdvwpw2xid.onion:5223"
it "should reject bracketed non-IPv6 server host" $
shouldReject @XFTPServer "xftp://1234-w==@[simplex.chat]:443"
where
Expand Down
28 changes: 27 additions & 1 deletion tests/FileDescriptionTests.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ module FileDescriptionTests where
import Control.Exception (bracket_)
import qualified Data.ByteString.Char8 as B
import qualified Data.Yaml as Y
import Simplex.FileTransfer.Client.Main (decodeWebURI, fileWebLink)
import Simplex.FileTransfer.Description
import Simplex.FileTransfer.Protocol
import qualified Simplex.Messaging.Crypto as C
import Simplex.Messaging.Encoding.String (StrEncoding (..))
import Simplex.Messaging.Protocol (EntityId (..))
import Simplex.Messaging.Protocol (EntityId (..), XFTPServer)
import Simplex.Messaging.ServiceScheme (ServiceScheme (..))
import System.Directory (removeFile)
import Test.Hspec hiding (fit, it)
Expand All @@ -29,6 +30,7 @@ fileDescriptionTests = do
describe "file description URIs" $ do
it "round trip file description URI" testFileDescriptionURI
it "round trip file description URI with extra JSON" testFileDescriptionURIExtras
it "encode IPv6 post-upload web link authority and preserve its fragment" testFileWebLinkIPv6

fileDescPath :: FilePath
fileDescPath = "tests/fixtures/file_description.yaml"
Expand Down Expand Up @@ -177,6 +179,30 @@ testFileDescriptionURIExtras = do
let descr = FileDescriptionURI SSSimplex vfd $ Just "{\"something\":\"extra\",\"more\":true}"
strDecode (strEncode descr) `shouldBe` Right descr

testFileWebLinkIPv6 :: IO ()
testFileWebLinkIPv6 = do
let ipv6Server = either error id (strDecode "xftp://abc=@[2001:db8::1]:5223") :: XFTPServer
ipv6FileDesc = withPrimaryServer ipv6Server fileDesc
case fileWebLink ipv6FileDesc of
Nothing -> expectationFailure "expected an IPv6 web link"
Just (authority, fragment) -> do
let webLink = "https://" <> authority <> "/#" <> fragment
authority `shouldBe` "[2001:db8::1]"
webLink `shouldBe` "https://[2001:db8::1]/#" <> fragment
expected <- either fail pure $ validateFileDescription ipv6FileDesc
decodeWebURI fragment `shouldBe` Right expected
(fst <$> fileWebLink fileDesc) `shouldBe` Just "example1.com"
where
withPrimaryServer :: XFTPServer -> FileDescription 'FRecipient -> FileDescription 'FRecipient
withPrimaryServer server (FileDescription party fdSize fdDigest key nonce fdChunkSize (chunk : chunks) redirect) =
FileDescription party fdSize fdDigest key nonce fdChunkSize (replaceChunk chunk : chunks) redirect
where
replaceChunk :: FileChunk -> FileChunk
replaceChunk (FileChunk chunkNo size digest (FileChunkReplica _ replicaId replicaKey : replicas)) =
FileChunk chunkNo size digest (FileChunkReplica server replicaId replicaKey : replicas)
replaceChunk c = c
withPrimaryServer _ fd = fd

withRemoveTmpFile :: IO () -> IO ()
withRemoveTmpFile =
bracket_
Expand Down
41 changes: 34 additions & 7 deletions tests/RemoteControl.hs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import Simplex.RemoteControl.Discovery (mkLastLocalHost, preferAddress)
import Simplex.RemoteControl.Invitation
( RCInvitation (..),
RCSignedInvitation,
RCVerifiedInvitation (..),
signInvitation,
verifySignedInvitation,
)
import Simplex.RemoteControl.Types
Expand All @@ -38,7 +40,8 @@ remoteControlTests :: Spec
remoteControlTests = do
describe "preferred bindings should go first" testPreferAddress
describe "Invitation parsing" $ do
it "should parse bracketed IPv6 host with port" testInvitationBracketedIPv6Host
it "should encode and parse bracketed IPv6 host with port" testInvitationBracketedIPv6Host
it "should encode, parse and verify signed IPv6 invitation" testSignedInvitationBracketedIPv6Host
it "should reject bracketed non-IPv6 host" testInvitationBracketedNonIPv6HostRejected
describe "New controller/host pairing" $ do
it "should connect to new pairing" testNewPairing
Expand Down Expand Up @@ -81,10 +84,9 @@ testPreferAddress = do
testInvitationBracketedIPv6Host :: IO ()
testInvitationBracketedIPv6Host = do
invitation <- testIPv6Invitation
let bracketedUri =
B.pack . replaceFirst "@2001:db8::1:" "@[2001:db8::1]:" . B.unpack $
strEncode invitation
let bracketedUri = strEncode invitation
expectedHost = either error id (strDecode "2001:db8::1") :: TransportHost
bracketedUri `shouldSatisfy` B.isInfixOf "@[2001:db8::1]:5223"
case strDecode bracketedUri of
Left err -> expectationFailure err
Right RCInvitation {host, port} -> do
Expand All @@ -94,9 +96,7 @@ testInvitationBracketedIPv6Host = do
testInvitationBracketedNonIPv6HostRejected :: IO ()
testInvitationBracketedNonIPv6HostRejected = do
invitation <- testIPv6Invitation
let bracketedUri =
B.pack . replaceFirst "@2001:db8::1:" "@[simplex.chat]:" . B.unpack $
strEncode invitation
let bracketedUri = B.pack . replaceFirst "@[2001:db8::1]:" "@[simplex.chat]:" . B.unpack $ strEncode invitation
case strDecode bracketedUri :: Either String RCInvitation of
Left _ -> pure ()
Right _ -> expectationFailure "expected parse failure for bracketed non-IPv6 host"
Expand All @@ -110,6 +110,33 @@ replaceFirst needle replacement = go
Just rest -> replacement <> rest
Nothing -> c : go cs

testSignedInvitationBracketedIPv6Host :: IO ()
testSignedInvitationBracketedIPv6Host = do
drg <- C.newRandom
(skey, sKey) <- atomically $ C.generateKeyPair @'C.Ed25519 drg
(idkey, idKey) <- atomically $ C.generateKeyPair @'C.Ed25519 drg
(dh, _) <- atomically $ C.generateKeyPair @'C.X25519 drg
let invitation =
RCInvitation
(C.KeyHash "test-ca")
(either error id $ strDecode "2001:db8::1")
5223
supportedRCPVRange
(J.String "app")
(MkSystemTime 0 0)
skey
idkey
dh
encoded = strEncode $ signInvitation sKey idKey invitation
encoded `shouldSatisfy` B.isInfixOf "@[2001:db8::1]:5223"
case strDecode encoded :: Either String RCSignedInvitation of
Left err -> expectationFailure err
Right signed -> case verifySignedInvitation signed of
Just (RCVerifiedInvitation RCInvitation {host, port}) -> do
host `shouldBe` either error id (strDecode "2001:db8::1")
port `shouldBe` 5223
Nothing -> expectationFailure "expected valid signed IPv6 invitation"

testIPv6Invitation :: IO RCInvitation
testIPv6Invitation = do
drg <- C.newRandom
Expand Down
Loading