!TE      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~   .File transfer and simple text message protocolNonek magic-wormholeKTextual representation of the format in which the directory tree is encodedmagic-wormholeOAn offer made by a sender as part of the Magic Wormhole file transfer protocol.wCurrently only supports sending simple text messages. A full version would also support sending files and directories.magic-wormholeA simple text message.magic-wormhole$Offer a File with filename and size.magic-wormholeOffer a Directorymagic-wormhole*Mode. Currently always "zipfile/deflated".magic-wormholeDirectory Name.magic-wormhole0size of the transmitted compressed data in bytes magic-wormhole2estimated total size of the uncompressed directory magic-wormhole*number of files and directories being sent   NoneMkq3magic-wormhole5Message received on initial connection to the server.magic-wormholeBA message to be displayed to users when they connect to the servermagic-wormholeRIf present, the server does not want the client to proceed. Here's the reason why.magic-wormholeA message sent to a mailbox.magic-wormhole/Which side sent the message. Might be our side.magic-wormhole-Which phase of the client protocol we are in.magic-wormhole&An identifier for the message. Unused.pAccording to the protocol docs, this should always be set, but the Python server will happily mirror an absent id field as .magic-wormholeBThe body of the message. To be interpreted by the client protocol.magic-wormhole]Identifier sent with every client message that is included in the matching server responses.magic-wormhole]How the client feels. Reported by the client to the server at the end of a wormhole session. magic-wormhole-The client had a great session with its peer.!magic-wormholeThe client never saw its peer."magic-wormhole)The client saw a peer it could not trust.#magic-wormhole$The client encountered some problem.$magic-wormholelShort string used to differentiate between echoes of our own messages and real messages from other clients.dTODO: This needs to be cleanly encoded to ASCII, so update the type or provide a smart constructor.&magic-wormholeShort string to identify the application. Clients must use the same application ID if they wish to communicate with each other.?Recommendation is to use "$DNSNAME/$APPNAME", e.g. the Python wormhole command-line tool uses %lothar.com/wormhole/text-or-file-xfer.(magic-wormhole6A message sent from a rendezvous client to the server.)magic-wormholeISet the application ID and the "side" for the duration of the connection.*magic-wormhole'Get a list of all allocated nameplates.+magic-wormhole&Ask the server to allocate a nameplate,magic-wormholeClaim a nameplate.-magic-wormholeRelease a claimed nameplate.\If no nameplate is provided, the server will attempt to release the nameplate claimed (via ,) earlier in this connection..magic-wormholeOpen a mailbox./magic-wormholeSend a message to an open mailbox. The message will be delivered to all connected clients that also have that mailbox open, including this one.0magic-wormholexClose a mailbox. Since only one mailbox can be open at a time, if mailbox isn't specified, then close the open mailbox.1magic-wormholeInternal "ping". Response is E. Used for testing.2magic-wormhole%The body of a Magic Wormhole message.WThis can be any arbitrary bytestring that is sent to or received from a wormhole peer.4magic-wormholeIdentifier for a mailbox.kA mailbox is a shared access point between Magic Wormhole peers within the same application (specified by &/). To get a mailbox, you must first acquire a :3 and then claim that nameplate for your side with  . A mailbox ID is defined in the  Lhttps://github.com/warner/magic-wormhole/blob/master/docs/server-protocol.mdspecc as a "large random string", but in practice is a 13 character, lower-case, alpha-numeric string.6magic-wormhole4A phase in the peer-to-peer (aka "client") protocol. Phases proceed in strict order: 7, 8 , then many 9.7magic-wormhole(Sent immediately on opening the mailbox.8magic-wormholeUsed to negotiate capabilities.9magic-wormhole^Reserved for application data. Messages with these phases will be delivered in numeric order.:magic-wormholeIdentifier for a "nameplate".A nameplate is a very short string that identifies one peer to another. Its purpose is to allow peers to find each other without having to communicate the 4_ identifier, which is generally too lengthy and cumbersome to be easily shared between humans.eTypically, one peer will allocate a nameplate and then communicate it out-of-band to the other peer.<magic-wormhole#A message received from the server.Some open questions: * general message stuff--how are we going to model this? * outgoing messages include a randomly generated idS field, which is returned by the server * messages from the server include  server_tx, a float timestamp recording when the server received the message * messages from the server that are direct responses include a  server_rx timestamp--unclear what this means? * do we want a separate Haskell type for each message type? e.g. PingMessage * if we do that, how do associate request/response pairs? e.g. PingMessage & PongMessage? * do we want to (can we even?) structurally distinguish between messages that make sense outside the scope of a binding (e.g. ping) and messages that only make sense after a bind (e.g. allocate)=magic-wormhole)Sent by the server on initial connection.>magic-wormholeSent in response to "list"?magic-wormholeSent in response to "allocate"@magic-wormholeSent in response to "claim"Amagic-wormholeSent in response to "release"Bmagic-wormholeA message sent to the mailboxCmagic-wormholeSent in response to "close"Dmagic-wormhole-Sent immediately after every message. Unused.Emagic-wormholeSent in response to "pong"Fmagic-wormholeZSent by the server when it receives something from the client that it does not understand.Hmagic-wormhole/The nameplate allocated to this connection (?).Imagic-wormhole*The mailbox claimed by this connection (?)Jmagic-wormhole&Message explaining what the problem isKmagic-wormhole$The message that caused the problem.magic-wormhole)Create a JSON object with a "type" field.=Use this to construct objects for client and server messages.Lmagic-wormhole7Get the name of the phase. Used to derive message keys.Mmagic-wormholeGenerate a random $; !"#$%&'()*+,-./0123456789:;<BF=>?@ACDEGHIJKLM;()*+,-./01<BF=>?@ACDEGHIJK&'$%M6789L23:;45 !"#7Low-level details for talking to a Magic Wormhole peer.NonePk{magic-wormhole3Something that went wrong with the client protocol.|magic-wormholeCWe received a message from the other side that we could not decrypt}magic-wormholeGWe could not determine the SecretBox nonce from the message we received~magic-wormholeNWe received a message for a phase that we have already received a message for.magic-wormholeThe purpose of a message.  combines this with the  to make a unique . Do not re-use a  to send more than message.magic-wormholeEncrypted text.magic-wormholeUnencrypted text.magic-wormholeMSPAKE2 key used for the duration of a Magic Wormhole peer-to-peer connection.You can obtain a  using  .,Individual messages will be encrypted using  (%), which must be given a key that's  generated from this one (see ).magic-wormhole1A connection to a peer via the Rendezvous server.Normally construct this with  .magic-wormhole'The application ID for this connection.magic-wormhole/The identifier for this side of the connection.magic-wormhole!Send a message to the other side.magic-wormhole&Receive a message from the other side.magic-wormhole&Send an encrypted message to the peer.magic-wormholePull a message from the peer and decrypt it. If the message fails to decrypt, an exception will be thrown, aborting the transaction and leaving the message on the queue.magic-wormhole;Encrypt a mailbox message, deriving the key from the phase.magic-wormholeEncrypt a message using  SecretBox. Get the key from . Decrypt with .magic-wormhole Decrypt a MailboxMessage using  SecretBox!. Derives the key from the phase.magic-wormholeDecrypt a message using  SecretBox. Get the key from . Encrypted using .magic-wormhole%Derive a one-off key from the SPAKE2 . Use this key only once.magic-wormhole Obtain a S for deriving a key to send a message that's part of a peer-to-peer communication.magic-wormholeConnection to the peermagic-wormhole$The key established for this sessionmagic-wormhole-Phase of the protocol this message representsmagic-wormholeContent of the messagemagic-wormholeConnection to the peermagic-wormhole$The key established for this sessionmagic-wormhole0The phase and content of the message we receivedmagic-wormhole Key established for this sessionmagic-wormhole-What this key is for. Normally created using .magic-wormhole.A key to use once to send or receive a message{}|~{}|~ PAKE exchange for Magic WormholeNonekfmagic-wormholeAn error that occured during .magic-wormhole:The version of the SPAKE2 protocol used by Magic Wormhole.magic-wormhole8The message we send to negotiate the shared session key.magic-wormhole0Exchange SPAKE2 keys with a Magic Wormhole peer. Throws an ) if we cannot parse the incoming message.magic-wormholeWEncode the bytes generated by the SPAKE2 algorithm into a Magic Wormhole message body.magic-wormholeeDecode a Magic Wormhole message body into bytes that can be used as input into the SPAKE2 algorithm.magic-wormhole;Construct a SPAKE2 protocol compatible with Magic Wormhole.magic-wormholeA connection to a peermagic-wormhole$The shared password. Construct with .magic-wormhole7A key that can be used for the remainder of the sessionSafekwmagic-wormholecA thing that gets numbered items and then buffers them so you can read them in order without gaps."counter" is an i that is used to determine the ordering of the elements, and "item" is the type of the items themselves.magic-wormholeDThe current value of the counter. The next item must have this rank.magic-wormholedWhere we store the items that have arrived out of order. A priority queue might be a better choice.magic-wormhole7How to rank items. Each item has a "rank", which is an M (specifically, a "counter"). Items are yielded in order, without gaps, by .magic-wormhole Create a  value for a series of item.magic-wormholeOInsert an item into the sequence. It may only be drawn from the sequence with  when its counter is next one.cIf the counter has already been past, don't insert it, since we'll never reach it. Instead return .magic-wormhole}Get and remove the next item from the sequence. This will block until there is an item with the exact rank we are expecting.magic-wormholeHow to rank itemsmagic-wormhole#The expected rank of the first itemmagic-wormhole How item are ordered in sequencemagic-wormhole The next itemPeer version exchangeNonekdzmagic-wormholeAn error occurred during .magic-wormhole;We could not interpret the other side's version informationmagic-wormhole^The other side sent us version information, but it does not match ours, so we cannot proceed.magic-wormholeGInformation about the versions supported by this Magic Wormhole client.There are no extant Magic Wormhole implementations that send any meaningful information in their versions message, so this is just a single-valued type.magic-wormhole8Exchange version information with a Magic Wormhole peer. Can throw an Error if something goes wrong.magic-wormholeA connection to a peermagic-wormhole&A shared session key. Obtain this via  .magic-wormholeShared version information Nonekmagic-wormhole2A Magic Wormhole peer-to-peer application session.Construct one of these using .;You get one of these after you have found a peer, successfully negotatiated a shared key, and verified that negotiation by exchanging versions. (Note that this does not include the "verifying" step mentioned in magic-wormhole's documentation, which is about a human being verifying the correctness of the code).fAll messages in this session, sent & received, are encrypted using keys derived from this shared key.magic-wormhole0Establish an encrypted connection between peers.Use this connection with .magic-wormhole\Run an action that communicates with a Magic Wormhole peer through an encrypted connection.Does the "pake" and "version" exchanges necessary to negotiate an encrypted connection and then runs the user-provided action. This action can then use  and * to send & receive messages from its peer. Can throw:{6, when we receive nonsensical data from the other peer , when SPAKE2 cryptography failsd, when we cannot agree on shared capabilities (this can sometimes imply SPAKE2 cryptography failure)magic-wormhole%Construct a new encrypted connection.magic-wormholemTake a successfully negotiated peer connection and run an action that sends and receives encrypted messages.(Establish an encrypted connection using .3Use this to communicate with a Magic Wormhole peer.Once you have the session, use . to send encrypted messages to the peer, and  to received decrypted messages.magic-wormhole&Send an encrypted message to the peer. Obtain an  with .PThe message will be encrypted using a one-off key deriving from the shared key.magic-wormhole*Receive a decrypted message from the peer. Obtain an  with .magic-wormhole&Derive a new key for the given purposeUConstruct a new key from the encrypted connection's session key for the given purposemagic-wormhole$Underlying to a peer. Get this with  .magic-wormholeHThe shared password that is the basis of the encryption. Construct with .magic-wormhole0Action to perform with the encrypted connection.magic-wormholeThe result of the actionSafekmagic-wormhole#Path to a websocket endpoint. e.g. /v1/foomagic-wormhole+Port number for a websocket endpoint. e.g. 80magic-wormhole)Host name for a websocket endpoint. e.g.  example.com.magic-wormhole$Endpoint for a websocket connection.Construct directly or with .magic-wormholeTurn a  into a  , if we can.rRequires that the URI has an authority (i.e. host & port). Discards information from scheme, query, and fragment.magic-wormholeParse a . None$79kBw"magic-wormhole$Error caused by misusing the client.magic-wormhole~We tried to do an RPC while another RPC with the same response type was in flight. See warner/magic-wormhole#260 for details.magic-wormholeITried to send a non-RPC as if it were an RPC (i.e. expecting a response).magic-wormhole7We sent a message that the server could not understand.magic-wormhole'Error due to weirdness from the server.magic-wormholeAServer sent us a response for something that we hadn't requested.magic-wormhole"We were sent a message other than Welcome on connect, or a Welcome message at any other time.magic-wormholeWe received an error? message for a message that's not expected to have a response.magic-wormhole0Clients are not welcome on the server right now.magic-wormhole3We couldn't understand the message from the server.magic-wormholeThe type of a response.?This is used pretty much only to match responses with requests.$XXX: Duplication with ServerMessage?magic-wormhole4Abstract type representing a Magic Wormhole session.Use  to get a ; on the Magic Wormhole Rendezvous server. Once you have a , use , , , , , , and , to communicate with the Rendezvous server.magic-wormholeThe AppID of this running sessionmagic-wormholeThe Side of this running sessionmagic-wormhole Create a new .magic-wormhole5Send a message to a Magic Wormhole Rendezvous server.magic-wormhole_Receive a message from a Magic Wormhole Rendezvous server. Blocks until such a message exists.magic-wormholeZRun a Magic Wormhole Rendezvous client. Use this to interact with a Magic Wormhole server. Will throw a ) if the server declares we are unwelcome.magic-wormhole(Make a request to the rendezvous server. Will throw a  if there's a problem.magic-wormhole@Set the application ID and side for the rest of this connection.3The Rendezvous protocol doesn't have a response to bind6, so there's no way to tell if it has had its effect.See 3https://github.com/warner/magic-wormhole/issues/261magic-wormholePing the server.dThis is an in-band ping, used mostly for testing. It is not necessary to keep the connection alive. Throws a 2 if the server rejects the message for any reason.magic-wormhole"List the nameplates on the server. Throws a 2 if the server rejects the message for any reason.magic-wormhole#Allocate a nameplate on the server. Throws a 2 if the server rejects the message for any reason.magic-wormhole Claim a nameplate on the server. Throws a 2 if the server rejects the message for any reason.magic-wormhole"Release a nameplate on the server.5TODO: Document semantics around "optional" nameplate.OTODO: Make this impossible to call unless we have already claimed a namespace. Throws a 2 if the server rejects the message for any reason.magic-wormholeOpen a mailbox on the server.If there's already a mailbox open, the server will send an error message. In the current implementation, that error will arise in a strange and unexpected place.See Jhttps://github.com/warner/magic-wormhole/issues/261#issuecomment-343192449magic-wormholeClose a mailbox on the server. Throws a 2 if the server rejects the message for any reason.magic-wormhole#Send a message to the open mailbox.magic-wormhole5Read a message from someone else from an open mailboxkWill block until we receive a message from someone who isn't us. Specifically, a message with a different side to us.+Will discard all messages that are from us.magic-wormhole$Read a message from an open mailbox.fWill block if there's no message, or if we're in no state to receive messages (e.g. no mailbox open).magic-wormholeUCalled when an RPC receives a message as a response that does not match the request.9As things are written, this should never happen, because  gotResponseY makes sure we only ever populate the response placeholder with something that matches.#TODO: Try to make this unnecessary.magic-wormhole8Called when we have received a response from the server.GTells anything waiting for the response that they can stop waiting now.magic-wormholeGCalled when we receive a message (possibly a response) from the server.magic-wormholeMap  ClientMessage to a response. & means that we do not need a response.magic-wormhole3Active WebSocket connection to a Rendezvous Server.magic-wormholeOpaque  object.magic-wormhole"An active session. Get this using .magic-wormholeMessage to send to the server.magic-wormhole"An active session. Get this using .magic-wormholeNext message from the server.magic-wormholeThe websocket to connect tomagic-wormhole;ID for your application (e.g. example.com/your-application)magic-wormholeIdentifier for your sidemagic-wormholeEJust an existing socket to use or Nothing to create and use a new onemagic-wormhole3Action to perform inside the Magic Wormhole sessionmagic-wormholeThe result of the actionmagic-wormhole(A Magic Wormhole session. Get one using .magic-wormhole#The RPC to send. Will fail with an Error if this is not a valid RPC.magic-wormholeThe result of an RPCA Magic Wormhole client.NonekC4 $%&'45:;M{4&'$%M:;45{ SafekE      !"##$%&&'()*++,-./011223456789:;<==>>?@ABCCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~M                                magic-wormhole-0.3.2-inplace MagicWormhole#MagicWormhole.Internal.FileTransferMagicWormhole.Internal.Messages%MagicWormhole.Internal.ClientProtocolMagicWormhole.Internal.Pake!MagicWormhole.Internal.SequentialMagicWormhole.Internal.Versions!MagicWormhole.Internal.WebSockets!MagicWormhole.Internal.Rendezvousclaim pakeExchangeopenMagicWormhole.Internal.Peer RendezvousPaths_magic_wormhole DirectoryModeZipFileDeflatedOfferMessageFile Directory directoryModedirNamezipSizenumBytesnumFiles$fToJSONDirectoryMode$fFromJSONDirectoryMode$fFromJSONOffer $fToJSONOffer$fEqDirectoryMode$fShowDirectoryMode $fEqOffer $fShowOfferWelcomeMessagemotdwelcomeErrorMessageMailboxMessagesidephase messageIDbody MessageIDMoodHappyLonelyScaryErrorySideAppID ClientMessageBindListAllocateClaimReleaseOpenAddClosePingBodyMailboxPhase PakePhase VersionPhaseApplicationPhase Nameplate ServerMessageWelcome Nameplates AllocatedClaimedReleasedClosedAckPongError nameplates nameplatemailbox errorMessageoriginal phaseName generateSide$fFromJSONPhase $fToJSONPhase$fFromJSONBody $fToJSONBody$fFromJSONMood $fToJSONMood$fToJSONClientMessage$fFromJSONClientMessage$fFromJSONMessageID$fToJSONMessageID$fToJSONServerMessage$fFromJSONServerMessage $fEqNameplate$fShowNameplate$fToJSONNameplate$fFromJSONNameplate $fEqPhase $fShowPhase $fEqMailbox $fShowMailbox$fToJSONMailbox$fFromJSONMailbox$fEqBody $fShowBody $fEqAppID $fShowAppID$fFromJSONAppID $fToJSONAppID$fEqSide $fShowSide$fFromJSONSide $fToJSONSide$fEqMood $fShowMood$fEqClientMessage$fShowClientMessage $fEqMessageID$fShowMessageID$fHashableMessageID$fEqMailboxMessage$fShowMailboxMessage$fEqWelcomeMessage$fShowWelcomeMessage$fEqServerMessage$fShowServerMessage PeerErrorCouldNotDecrypt InvalidNonceMessageOutOfOrderPurpose CipherTextcipherTextToByteString PlainTextplainTextToByteString SessionKey ConnectionappIDourSidesendreceive sendEncryptedreceiveEncryptedencryptdecrypt deriveKey phasePurpose$fExceptionPeerError $fEqPlainText$fOrdPlainText$fShowPlainText$fEqCipherText$fOrdCipherText$fShowCipherText $fEqPeerError$fShowPeerError PakeErrorspakeBytesToMessageBodymessageBodyToSpakeBytes$fFromJSONSpake2Message$fToJSONSpake2Message$fExceptionPakeError$fEqSpake2Message$fShowSpake2Message $fEqPakeError$fShowPakeError Sequential sequenceByinsertnext VersionsError ParseErrorVersionMismatchVersionsversionExchange$fFromJSONVersions$fToJSONVersions$fExceptionVersionsError $fEqVersions$fShowVersions$fEqVersionsError$fShowVersionsErrorEncryptedConnectionwithEncryptedConnection sendMessagereceiveMessagePathPortHostnameWebSocketEndpointuriToWebSocketEndpointparseWebSocketEndpoint$fEqWebSocketEndpoint$fShowWebSocketEndpoint ClientError AlreadySentNotAnRPC BadRequest ServerErrorResponseWithoutRequestUnexpectedMessageErrorForNonRequest UnwelcomeSession runClientpinglistallocatereleaseclose$fExceptionServerError$fExceptionClientError$fEqResponseType$fShowResponseType$fGenericResponseType$fHashableResponseType$fEqServerError$fShowServerError$fEqClientError$fShowClientErrorbase Data.FoldablenullobjectWithTypePsaltine-0.1.0.1-cb7dcc12f30f511fc39dbe3564ae42306b10ef7012719233d11e6de12ef9cc98Crypto.Saltine.Core.SecretBoxKeyencryptMessagedecryptMessageSpake2Protocol Spake2MessagewormholeSpakeProtocolMspake2-0.4.2-19bafa227afe28a16e51415ba0f6dd244921553fb3fb8b2423f3a3209e1ed32b Crypto.Spake2 makePasswordGHC.EnumEnumcurrentbufferrankghc-prim GHC.TypesFalseestablishEncryptionnewEncryptedConnectionrunEncryptedConnectionTnetwork-uri-2.6.1.0-af8e5231e7387572bad976289b73fecd50e3ff549adb1d9217ca966d97becd4f Network.URIURI ResponseType sessionAppID sessionSidenewrpcbindaddreadFromMailboxreadFromMailbox'unexpectedMessage gotResponse gotMessageexpectedResponse GHC.MaybeNothingversion getBinDir getLibDir getDynLibDir getDataDir getLibexecDir getSysconfDirgetDataFileName