    -- | TLS record layer in Tx direction
    module Network.TLS.Record.Send (
        encodeRecord12,
        encodeRecord13,
        sendBytes,
    ) where

    import Network.TLS.Cipher
    import Network.TLS.Context.Internal
    import Network.TLS.Hooks
    import Network.TLS.Imports
    import Network.TLS.Packet
    import Network.TLS.Record
    import Network.TLS.Struct

    import Control.Concurrent.MVar
    import Control.Monad.State.Strict
    import qualified Data.ByteString as B

    encodeRecordM :: Record Plaintext -> RecordM ByteString
    encodeRecordM :: Record Plaintext -> RecordM ByteString
    encodeRecordM Record Plaintext
    record = do
        erecord <- Record Plaintext -> RecordM (Record Ciphertext)
    encryptRecord Record Plaintext
    record
        let (hdr, content) = recordToRaw erecord
        return $ B.concat [encodeHeader hdr, content]

    ----------------------------------------------------------------

    encodeRecord12 :: Context -> Record Plaintext -> IO (Either TLSError ByteString)
    encodeRecord12 :: Context -> Record Plaintext -> IO (Either TLSError ByteString)
    encodeRecord12 Context
    ctx = Context -> RecordM ByteString -> IO (Either TLSError ByteString)
    forall a. Context -> RecordM a -> IO (Either TLSError a)
    prepareRecord12 Context
    ctx (RecordM ByteString -> IO (Either TLSError ByteString))
    -> (Record Plaintext -> RecordM ByteString)
    -> Record Plaintext
    -> IO (Either TLSError ByteString)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Record Plaintext -> RecordM ByteString
    encodeRecordM

    -- before TLS 1.1, the block cipher IV is made of the residual of the previous block,
    -- so we use cstIV as is, however in other case we generate an explicit IV
    prepareRecord12 :: Context -> RecordM a -> IO (Either TLSError a)
    prepareRecord12 :: forall a. Context -> RecordM a -> IO (Either TLSError a)
    prepareRecord12 Context
    ctx RecordM a
    f = do
        txState <- MVar RecordState -> IO RecordState
    forall a. MVar a -> IO a
    readMVar (MVar RecordState -> IO RecordState)
    -> MVar RecordState -> IO RecordState
    forall a b. (a -> b) -> a -> b
    $ Context -> MVar RecordState
    ctxTxRecordState Context
    ctx
        let sz = case RecordState -> Maybe Cipher
    stCipher RecordState
    txState of
                Maybe Cipher
    Nothing -> Int
    0
                Just Cipher
    cipher ->
                    if BulkFunctions -> Bool
    hasRecordIV (BulkFunctions -> Bool) -> BulkFunctions -> Bool
    forall a b. (a -> b) -> a -> b
    $ Bulk -> BulkFunctions
    bulkF (Bulk -> BulkFunctions) -> Bulk -> BulkFunctions
    forall a b. (a -> b) -> a -> b
    $ Cipher -> Bulk
    cipherBulk Cipher
    cipher
                        then Bulk -> Int
    bulkIVSize (Bulk -> Int) -> Bulk -> Int
    forall a b. (a -> b) -> a -> b
    $ Cipher -> Bulk
    cipherBulk Cipher
    cipher
                        else Int
    0 -- to not generate IV
        if sz > 0
            then do
                newIV <- getStateRNG ctx sz
                runTxRecordState ctx (modify (setRecordIV newIV) >> f)
            else runTxRecordState ctx f

    ----------------------------------------------------------------

    encodeRecord13 :: Context -> Record Plaintext -> IO (Either TLSError ByteString)
    encodeRecord13 :: Context -> Record Plaintext -> IO (Either TLSError ByteString)
    encodeRecord13 Context
    ctx = Context -> RecordM ByteString -> IO (Either TLSError ByteString)
    forall a. Context -> RecordM a -> IO (Either TLSError a)
    prepareRecord13 Context
    ctx (RecordM ByteString -> IO (Either TLSError ByteString))
    -> (Record Plaintext -> RecordM ByteString)
    -> Record Plaintext
    -> IO (Either TLSError ByteString)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Record Plaintext -> RecordM ByteString
    encodeRecordM

    prepareRecord13 :: Context -> RecordM a -> IO (Either TLSError a)
    prepareRecord13 :: forall a. Context -> RecordM a -> IO (Either TLSError a)
    prepareRecord13 = Context -> RecordM a -> IO (Either TLSError a)
    forall a. Context -> RecordM a -> IO (Either TLSError a)
    runTxRecordState

    ----------------------------------------------------------------

    sendBytes :: Context -> ByteString -> IO ()
    sendBytes :: Context -> ByteString -> IO ()
    sendBytes Context
    ctx ByteString
    dataToSend = do
        Context -> (Logging -> IO ()) -> IO ()
    withLog Context
    ctx ((Logging -> IO ()) -> IO ()) -> (Logging -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Logging
    logging -> Logging -> ByteString -> IO ()
    loggingIOSent Logging
    logging ByteString
    dataToSend
        Context -> ByteString -> IO ()
    contextSend Context
    ctx ByteString
    dataToSend