-- {-# OPTIONS_GHC -cpp -fglasgow-exts -package hsgnutls -package Network.HaskellNet #-} -- examples to connect server by hsgnutls module TLSStream ( connectTLS , connectTLSPort , TlsSession , sess ) where import Network.GnuTLS import Network import Network.HaskellNet.BSStream import Data.ByteString (ByteString) import qualified Data.ByteString.Char8 as BS import qualified Data.ByteString.Internal as BSB import System.IO import Data.IORef import Control.Monad import Foreign.ForeignPtr import Foreign.Ptr data TlsSession t = TlsSession { sess :: Session t , hdl :: Handle , buf :: IORef ByteString } fromSession :: Handle -> Session t -> IO (TlsSession t) fromSession h s = do newbuf <- newIORef BS.empty return $ TlsSession s h newbuf connectTLS :: HostName -> PortNumber -> IO (TlsSession Client) connectTLS host port = connectTLSPort host (PortNumber port) connectTLSPort :: HostName -> PortID -> IO (TlsSession Client) connectTLSPort host port = do h <- connectTo host port s <- tlsClient [ handle :=> return h , priorities := [CrtX509, CrtOpenpgp]] cred <- certificateCredentials set s [ credentials := cred] handshake s fromSession h s bufLen = 4096 extendBuf sess@(TlsSession s _ buf) = do res <- mallocForeignPtrBytes bufLen len <- withForeignPtr res (\p -> tlsRecv s p bufLen) modifyIORef buf (flip BS.append $ BSB.fromForeignPtr res 0 len) return len doWhile cond execute = do f <- cond when f $ (execute >> doWhile cond execute) instance BSStream (TlsSession t) where bsGetLine sess@(TlsSession s _ buf) = do doWhile (readIORef buf >>= return . BS.notElem '\n') (extendBuf sess) bufstr' <- readIORef buf let (line, rest) = BS.span (/='\n') bufstr' writeIORef buf $ BS.tail rest return line bsGet sess@(TlsSession s _ buf) len = do doWhile (readIORef buf >>= return . ( (tlsSend s (plusPtr ptr off) len) return () where (fptr, off, len) = BSB.toForeignPtr bs bsPutNoFlush = bsPut bsFlush _ = return () bsClose (TlsSession s _ _) = bye s ShutRdwr