hs-tls/core/Network/TLS/Core.hs

103 lines
4.3 KiB
Haskell
Raw Normal View History

2011-03-02 08:43:05 +00:00
{-# OPTIONS_HADDOCK hide #-}
{-# LANGUAGE DeriveDataTypeable, OverloadedStrings #-}
2011-03-01 20:01:40 +00:00
-- |
-- Module : Network.TLS.Core
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- Stability : experimental
-- Portability : unknown
--
module Network.TLS.Core
2012-03-27 07:57:51 +00:00
(
-- * Internal packet sending and receiving
sendPacket
, recvPacket
-- * Initialisation and Termination of context
, bye
, handshake
, HandshakeFailed(..)
, ConnectionNotEstablished(..)
-- * Next Protocol Negotiation
, getNegotiatedProtocol
-- * High level API
, sendData
, recvData
, recvData'
) where
2011-03-01 20:01:40 +00:00
import Network.TLS.Context
2011-03-01 20:01:40 +00:00
import Network.TLS.Struct
import Network.TLS.IO
2012-04-27 06:28:17 +00:00
import Network.TLS.Handshake
import qualified Network.TLS.State as S
import qualified Data.ByteString as B
import Data.ByteString.Char8 ()
2011-03-01 20:01:40 +00:00
import qualified Data.ByteString.Lazy as L
import Control.Monad.State
2011-03-01 20:01:40 +00:00
2011-03-02 08:43:05 +00:00
-- | notify the context that this side wants to close connection.
-- this is important that it is called before closing the handle, otherwise
-- the session might not be resumable (for version < TLS1.2).
--
-- this doesn't actually close the handle
2012-03-15 07:53:03 +00:00
bye :: MonadIO m => Context -> m ()
bye ctx = sendPacket ctx $ Alert [(AlertLevel_Warning, CloseNotify)]
2011-03-01 20:01:40 +00:00
-- | If the Next Protocol Negotiation extension has been used, this will
-- return get the protocol agreed upon.
getNegotiatedProtocol :: MonadIO m => Context -> m (Maybe B.ByteString)
getNegotiatedProtocol ctx = usingState_ ctx S.getNegotiatedProtocol
2011-03-02 08:43:05 +00:00
-- | sendData sends a bunch of data.
-- It will automatically chunk data to acceptable packet size
2012-03-15 07:53:03 +00:00
sendData :: MonadIO m => Context -> L.ByteString -> m ()
2012-01-25 16:03:31 +00:00
sendData ctx dataToSend = checkValid ctx >> mapM_ sendDataChunk (L.toChunks dataToSend)
2012-03-27 07:57:51 +00:00
where sendDataChunk d
| B.length d > 16384 = do
let (sending, remain) = B.splitAt 16384 d
sendPacket ctx $ AppData sending
sendDataChunk remain
| otherwise = sendPacket ctx $ AppData d
-- | recvData get data out of Data packet, and automatically renegotiate if
2011-03-02 08:43:05 +00:00
-- a Handshake ClientHello is received
2012-03-15 07:53:03 +00:00
recvData :: MonadIO m => Context -> m B.ByteString
recvData ctx = do
2012-03-27 07:57:51 +00:00
checkValid ctx
pkt <- recvPacket ctx
case pkt of
-- on server context receiving a client hello == renegotiation
2012-11-16 15:37:05 +00:00
Right (Handshake [ch@(ClientHello _ _ _ _ _ _ (Just _))]) ->
-- reject renegotiation with SSLv2 header
case roleParams $ ctxParams ctx of
Server sparams -> error "assert, deprecated hello request in server context"
Client {} -> error "assert, unexpected client hello in client context"
2012-03-27 07:57:51 +00:00
Right (Handshake [ch@(ClientHello {})]) ->
case roleParams $ ctxParams ctx of
Server sparams -> handshakeServerWith sparams ctx ch >> recvData ctx
2012-10-20 08:00:55 +00:00
Client {} -> error "assert, unexpected client hello in client context"
2012-03-27 07:57:51 +00:00
-- on client context, receiving a hello request == renegotiation
Right (Handshake [HelloRequest]) ->
case roleParams $ ctxParams ctx of
2012-10-20 08:00:55 +00:00
Server {} -> error "assert, unexpected hello request in server context"
Client cparams -> handshakeClient cparams ctx >> recvData ctx
2012-03-27 07:57:51 +00:00
Right (Alert [(AlertLevel_Fatal, _)]) -> do
setEOF ctx
return B.empty
Right (Alert [(AlertLevel_Warning, CloseNotify)]) -> do
setEOF ctx
return B.empty
Right (AppData "") -> recvData ctx
Right (AppData x) -> return x
Right p -> error ("error unexpected packet: " ++ show p)
Left err -> error ("error received: " ++ show err)
{-# DEPRECATED recvData' "use recvData that returns strict bytestring" #-}
-- | same as recvData but returns a lazy bytestring.
2012-03-15 07:53:03 +00:00
recvData' :: MonadIO m => Context -> m L.ByteString
recvData' ctx = recvData ctx >>= return . L.fromChunks . (:[])