{-# LANGUAGE OverloadedStrings #-}
----------------------------------------------------------------
-- |
-- Module      : Pipes.Noise
-- Maintainer  : John Galt <jgalt@centromere.net>
-- Stability   : experimental
-- Portability : POSIX

module Pipes.Noise
  ( -- * Types
    MessagePipe,
    -- * Pipes
    messageEncryptPipe,
    messageDecryptPipe
  ) where

import Control.Concurrent.MVar (MVar, putMVar, takeMVar)
import Control.Monad           (forever)
import Data.ByteString         (ByteString)
import Pipes                   (Pipe, await, yield, lift)

import Crypto.Noise.Cipher     (Cipher)
import Crypto.Noise.Handshake
import Crypto.Noise.Types      (Plaintext(..), bsToSB', sbToBS')

-- | Message pipes transform ByteStrings.
type MessagePipe = Pipe ByteString ByteString

-- | Creates a new 'MessagePipe' exclusively for encryption.
messageEncryptPipe :: Cipher c
                   => MVar (SendingCipherState c)
                   -> MessagePipe IO r
messageEncryptPipe csmv = forever $ do
  msg <- await

  encState <- lift $ takeMVar csmv
  let pt = Plaintext . bsToSB' $ msg
      (ct, encState') = encryptPayload pt encState
  lift $ putMVar csmv encState'

  yield ct

-- | Creates a new 'MessagePipe' exclusively for decryption.
messageDecryptPipe :: Cipher c
                   => MVar (ReceivingCipherState c)
                   -> MessagePipe IO r
messageDecryptPipe csmv = forever $ do
  msg <- await

  decState <- lift $ takeMVar csmv
  let (Plaintext pt, decState') = decryptPayload msg decState
  lift $ putMVar csmv decState'

  yield . sbToBS' $ pt