    -- |
    -- Module      : Network.TLS.Handshake
    -- License     : BSD-style
    -- Maintainer  : Vincent Hanquez <vincent@snarc.org>
    -- Stability   : experimental
    -- Portability : unknown
    --
    module Network.TLS.Handshake
        ( handshake
        , handshakeWith
        , handshakeClientWith
        , handshakeServerWith
        , handshakeClient
        , handshakeServer
        ) where

    import Network.TLS.Context.Internal
    import Network.TLS.Struct

    import Network.TLS.Handshake.Common
    import Network.TLS.Handshake.Client
    import Network.TLS.Handshake.Server

    import Control.Monad.State.Strict

    -- | Handshake for a new TLS connection
    -- This is to be called at the beginning of a connection, and during renegotiation
    handshake :: MonadIO m => Context -> m ()
    handshake :: forall (m :: * -> *). MonadIO m => Context -> m ()
    handshake Context
    ctx =
        IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ Context -> IO () -> IO ()
    forall a. Context -> IO a -> IO a
    withRWLock Context
    ctx (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Context -> IO () -> IO ()
    handleException Context
    ctx (Context -> Context -> IO ()
    ctxDoHandshake Context
    ctx Context
    ctx)

    -- Handshake when requested by the remote end
    -- This is called automatically by 'recvData', in a context where the read lock
    -- is already taken.  So contrary to 'handshake' above, here we only need to
    -- call withWriteLock.
    handshakeWith :: MonadIO m => Context -> Handshake -> m ()
    handshakeWith :: forall (m :: * -> *). MonadIO m => Context -> Handshake -> m ()
    handshakeWith Context
    ctx Handshake
    hs =
        IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ Context -> IO () -> IO ()
    forall a. Context -> IO a -> IO a
    withWriteLock Context
    ctx (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Context -> IO () -> IO ()
    handleException Context
    ctx (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Context -> Context -> Handshake -> IO ()
    ctxDoHandshakeWith Context
    ctx Context
    ctx Handshake
    hs