-- GENERATED by C->Haskell Compiler, version 0.16.0 Crystal Seed, 24 Jan 2009 (Haskell)
-- Edit the ORIGNAL .chs file instead!


{-# LINE 1 "./Network/GnuTLS/GnuTLS.chs" #-}
module Network.GnuTLS.GnuTLS 
    (-- * Enumerations
     CipherAlgorithm(..), KxAlgorithm(..), ParamsType(..), CredentialsType(..),
     MacAlgorithm(..), DigestAlgorithm(..), CompressionMethod(..), ConnectionEnd(..),
     AlertLevel(..), AlertDescription(..), HandshakeDescription(..), CertificateStatus(..), 
     CertificateRequest(..), CloseRequest(..), Protocol(..), 
     CertificateType(..), X509CertificateFormat(..), PkAlgorithm(..), SignAlgorithm(..), 
     -- * Types
     Session, DH, RSA, AnonymousServerCredentials, AnonymousClientCredentials,
     Server, Client, Transport, CertificateCredentials,Datum(..),
     -- * Priority
     SetPriority(..), setDefaultPriority, setDefaultExportPriority,
     -- * Credentials
     SetCredentials(..), Clear(..),
     -- * Creating connections
     tlsClient, tlsServer,
     -- * Session Accessors
     priorities, credentials, dhPrimeBits, transport, handle, clientCert,
    -- * Managing connection
    handshake, rehandshake, bye, 
    setMaxHandshakePacketLength,
    -- * Querying connection attributes
    serverWantedAuth, verifyPeer, isResumed, 
    getAlert, getCipher, getKx, getMac, getCompression, getCertificateType, getProtocol, 
    getCredentialsType,
    getServerCredentialsType, getClientCredentialsType,
    getPeersCertificatesRaw,
    -- * Sending and receiving data
    tlsSend, tlsSendString, tlsRecv, tlsRecvString, tlsCheckPending,
    -- * Certificate functions
    certificateCredentials, freeKeys, freeCas, freeCaNames, freeCrls,
    certificateTrustFile, certificateCrlFile, certificateKeyFile,
    -- * Miscellaneous
     anonymousServerCredentials, anonymousClientCredentials,
     SetDHParams(..), CredParameter(..),
     newDH, newRSA,cipherKeySize,cipherSuiteName,
     version, gnutlsGlobalInit 
    ) where

import Control.Concurrent
import Data.Bits((.&.), (.|.))
import Data.IORef(newIORef, readIORef)
import Foreign
import Foreign.C
import qualified Foreign.Concurrent as FC
import Foreign.Ptr
import System.IO
import System.IO.Unsafe
import Network.GnuTLS.Attributes
import Network.GnuTLS.Internals
import Network.GnuTLS.RefCount



{-# LINE 64 "./Network/GnuTLS/GnuTLS.chs" #-}


--------------------------------------------------------------------------------
------------------------------   Types   ---------------------------------------
--------------------------------------------------------------------------------

data DH  = DH  (ForeignPtr ())! RefCount
data RSA = RSA (ForeignPtr ())! RefCount
data AnonymousServerCredentials = ASC (ForeignPtr ())! RefCount
data AnonymousClientCredentials = ACC (ForeignPtr ())! RefCount
data CertificateCredentials     = CC  (ForeignPtr ())! RefCount

data Server
data Client
type Transport = Ptr () -> Int -> Ptr CInt -> IO Int

withDH  (DH fp _)  = withForeignPtr fp
withRSA (RSA fp _) = withForeignPtr fp
withAnonymousServerCredentials (ASC fp _) = withForeignPtr fp
withAnonymousClientCredentials (ACC fp _) = withForeignPtr fp
withCertificateCredentials     (CC fp _)  = withForeignPtr fp


--------------------------------------------------------------------------------
-------------------------   Show Functions   -----------------------------------
--------------------------------------------------------------------------------

instance Show AlertDescription where
    show a = unsafePerformIO $ gnutlsAlertGetName a
gnutlsAlertGetName :: AlertDescription -> IO (String)
gnutlsAlertGetName a1 =
  let {a1' = enumCInt a1} in 
  gnutlsAlertGetName'_ a1' >>= \res ->
  safePeekCString res >>= \res' ->
  return (res')
{-# LINE 94 "./Network/GnuTLS/GnuTLS.chs" #-}

instance Show CipherAlgorithm where
    show a = unsafePerformIO $ gnutlsCipherGetName a
gnutlsCipherGetName :: CipherAlgorithm -> IO (String)
gnutlsCipherGetName a1 =
  let {a1' = enumCInt a1} in 
  gnutlsCipherGetName'_ a1' >>= \res ->
  safePeekCString res >>= \res' ->
  return (res')
{-# LINE 98 "./Network/GnuTLS/GnuTLS.chs" #-}

instance Show MacAlgorithm where
    show a = unsafePerformIO $ gnutlsMacGetName a
gnutlsMacGetName :: MacAlgorithm -> IO (String)
gnutlsMacGetName a1 =
  let {a1' = enumCInt a1} in 
  gnutlsMacGetName'_ a1' >>= \res ->
  safePeekCString res >>= \res' ->
  return (res')
{-# LINE 102 "./Network/GnuTLS/GnuTLS.chs" #-}

instance Show CompressionMethod where
    show a = unsafePerformIO $ gnutlsCompressionGetName a
gnutlsCompressionGetName :: CompressionMethod -> IO (String)
gnutlsCompressionGetName a1 =
  let {a1' = enumCInt a1} in 
  gnutlsCompressionGetName'_ a1' >>= \res ->
  safePeekCString res >>= \res' ->
  return (res')
{-# LINE 106 "./Network/GnuTLS/GnuTLS.chs" #-}

instance Show KxAlgorithm where
    show a = unsafePerformIO $ gnutlsKxGetName a
gnutlsKxGetName :: KxAlgorithm -> IO (String)
gnutlsKxGetName a1 =
  let {a1' = enumCInt a1} in 
  gnutlsKxGetName'_ a1' >>= \res ->
  safePeekCString res >>= \res' ->
  return (res')
{-# LINE 110 "./Network/GnuTLS/GnuTLS.chs" #-}

instance Show CertificateType where
    show a = unsafePerformIO $ gnutlsCertificateTypeGetName a
gnutlsCertificateTypeGetName :: CertificateType -> IO (String)
gnutlsCertificateTypeGetName a1 =
  let {a1' = enumCInt a1} in 
  gnutlsCertificateTypeGetName'_ a1' >>= \res ->
  safePeekCString res >>= \res' ->
  return (res')
{-# LINE 114 "./Network/GnuTLS/GnuTLS.chs" #-}

instance Show Protocol where
    show a = unsafePerformIO $ gnutlsProtocolGetName a
gnutlsProtocolGetName :: Protocol -> IO (String)
gnutlsProtocolGetName a1 =
  let {a1' = enumCInt a1} in 
  gnutlsProtocolGetName'_ a1' >>= \res ->
  safePeekCString res >>= \res' ->
  return (res')
{-# LINE 118 "./Network/GnuTLS/GnuTLS.chs" #-}

instance Show PkAlgorithm where
    show a = unsafePerformIO $ gnutlsPkAlgorithmGetName a
gnutlsPkAlgorithmGetName :: PkAlgorithm -> IO (String)
gnutlsPkAlgorithmGetName a1 =
  let {a1' = enumCInt a1} in 
  gnutlsPkAlgorithmGetName'_ a1' >>= \res ->
  safePeekCString res >>= \res' ->
  return (res')
{-# LINE 122 "./Network/GnuTLS/GnuTLS.chs" #-}

instance Show SignAlgorithm where
    show a = unsafePerformIO $ gnutlsSignAlgorithmGetName a
gnutlsSignAlgorithmGetName :: SignAlgorithm -> IO (String)
gnutlsSignAlgorithmGetName a1 =
  let {a1' = enumCInt a1} in 
  gnutlsSignAlgorithmGetName'_ a1' >>= \res ->
  safePeekCString res >>= \res' ->
  return (res')
{-# LINE 126 "./Network/GnuTLS/GnuTLS.chs" #-}

--------------------------------------------------------------------------------
--------------------------   Set Priority   ------------------------------------
--------------------------------------------------------------------------------

setpwrap :: Enum e => (Ptr () -> Ptr CInt -> IO CInt) -> Session t -> [e] -> IO ()
setpwrap comp s x = do
  withEnumList0 x $ \e -> do
  withSession s   $ \p -> do
  comp p e >>= throwGnutlsIf

-- | Set the priority of the specified category.
-- On servers this means the set of acceptable values,
-- on clients it sets the priorities.
class SetPriority a where setPriority :: Session t -> [a] -> IO ()

instance SetPriority CipherAlgorithm where 
  setPriority = setpwrap gnutls_cipher_set_priority
{-# LINE 144 "./Network/GnuTLS/GnuTLS.chs" #-}

instance SetPriority MacAlgorithm where 
  setPriority = setpwrap gnutls_mac_set_priority
{-# LINE 147 "./Network/GnuTLS/GnuTLS.chs" #-}

instance SetPriority CompressionMethod where 
  setPriority = setpwrap gnutls_compression_set_priority
{-# LINE 150 "./Network/GnuTLS/GnuTLS.chs" #-}

instance SetPriority KxAlgorithm where 
  setPriority = setpwrap gnutls_kx_set_priority
{-# LINE 153 "./Network/GnuTLS/GnuTLS.chs" #-}

instance SetPriority Protocol where 
  setPriority = setpwrap gnutls_protocol_set_priority
{-# LINE 156 "./Network/GnuTLS/GnuTLS.chs" #-}

instance SetPriority CertificateType where 
  setPriority = setpwrap gnutls_certificate_type_set_priority
{-# LINE 159 "./Network/GnuTLS/GnuTLS.chs" #-}

-- | Set default priorities. This is called whenever a new 'Session' is created to 
-- ensure sensible defaults. 
setDefaultPriority :: Session t -> IO ()
setDefaultPriority a1 =
  withSession a1 $ \a1' -> 
  setDefaultPriority'_ a1' >>= \res ->
  return ()
{-# LINE 163 "./Network/GnuTLS/GnuTLS.chs" #-}
-- | Set default priorities conforming with various export regulations.
-- /Includes weak algorithms./
setDefaultExportPriority :: Session t -> IO ()
setDefaultExportPriority a1 =
  withSession a1 $ \a1' -> 
  setDefaultExportPriority'_ a1' >>= \res ->
  return ()
{-# LINE 166 "./Network/GnuTLS/GnuTLS.chs" #-}


--------------------------------------------------------------------------------
------------------------   Setting Credentials   -------------------------------
--------------------------------------------------------------------------------

-- | Set the credentials associated with a session.
class SetCredentials st a where setCredentials :: Session st -> a -> IO ()
instance SetCredentials st a => SetCredentials st (IO a) where 
  setCredentials s c = setCredentials s =<< c
instance SetCredentials Server AnonymousServerCredentials where 
  setCredentials s (ASC a rc) = setcred_ s CrdAnon (castForeignPtr a)
instance SetCredentials Client AnonymousClientCredentials where 
  setCredentials s (ACC a rc) = setcred_ s CrdAnon (castForeignPtr a)
instance SetCredentials t CertificateCredentials where 
  setCredentials s (CC a rc) = setcred_ s CrdCertificate (castForeignPtr a)

setcred_ :: Session t -> CredentialsType -> ForeignPtr a -> IO ()
setcred_ (Session sfp refc) ct fp = do
  withForeignPtr sfp $ \sptr ->     do
  withForeignPtr fp  $ \dptr ->     do
  gnutls_credentials_set sptr (enumCInt ct) (castPtr dptr) >>= throwGnutlsIf
  addRefFinalizer refc (touchForeignPtr fp)

-- | Used to clear all credentials associated with a session.
data Clear = Clear
instance SetCredentials t Clear where
  setCredentials s _ = withSession s (\s -> gnutls_credentials_clear s >> return ())

--------------------------------------------------------------------------------
---------------------------   Session Creation   -------------------------------
--------------------------------------------------------------------------------

tlsClient :: [AttrOp (Session Client)] -> IO (Session Client)
tlsClient p = do s <- newSession Client
                 set s p
                 return s

tlsServer :: [AttrOp (Session Server)] -> IO (Session Server)
tlsServer p = do s <- newSession Server
                 set s p
                 return s


newSession :: ConnectionEnd -> IO (Session t)
newSession ce = gnutlsGlobalInit >> alloca (\err -> do
  let efun b l e = putStrLn "TLS pull/push functions not set" >> return 0
  ef1 <- newStablePtr efun
  ef2 <- newStablePtr efun
  sp <- init_session_wrap (enumCInt ce) ef1 ef2 err
  peek err >>= throwGnutlsIf
  rc <- newRefCount (replace_transport_stable_ptrs sp stableNull stableNull >> gnutls_deinit sp)
  ps <- FC.newForeignPtr sp (freeRef rc)
  return $ Session ps rc)

stableNull = castPtrToStablePtr nullPtr

foreign import ccall unsafe "TLS.h gnutls_init" gnutls_init :: Ptr (Ptr ()) -> CInt -> IO CInt
foreign import ccall unsafe "TLS.h gnutls_deinit" gnutls_deinit :: Ptr () -> IO ()

foreign import ccall unsafe "TLS.h init_session_wrap"
  init_session_wrap :: CInt -> StablePtr Transport -> StablePtr Transport -> Ptr CInt -> IO (Ptr ())
--------------------------------------------------------------------------------
-------------------------   Session Accessors   --------------------------------
--------------------------------------------------------------------------------

priorities :: SetPriority a => WriteAttr (Session t) [a]
priorities = writeAttr setPriority

credentials :: SetCredentials t a => WriteAttr (Session t) a
credentials = writeAttr setCredentials

dhPrimeBits :: ReadWriteAttr (Session t) Int Int
dhPrimeBits = newAttr get set
    where get s   = withSession s gnutls_dh_get_prime_bits  >>= return . fromIntegral
          set s v = withSession s (\sp -> gnutls_dh_set_prime_bits sp (fromIntegral v))


transport :: ReadWriteAttr (Session t) (Transport,Transport) (Transport,Transport)
transport = newAttr gnutls_transport_get_ptr2 set
    where set s (a,b) =  do a' <- newStablePtr a
                            b' <- newStablePtr b
                            withSession s $ \sp -> replace_transport_stable_ptrs sp a' b'

gnutls_transport_get_ptr2 :: Session t -> IO (Transport, Transport)
gnutls_transport_get_ptr2 a1 =
  withSession a1 $ \a1' -> 
  alloca $ \a2' -> 
  alloca $ \a3' -> 
  gnutls_transport_get_ptr2'_ a1' a2' a3' >>= \res ->
  ptrDeS a2'>>= \a2'' -> 
  ptrDeS a3'>>= \a3'' -> 
  return (a2'', a3'')
{-# LINE 269 "./Network/GnuTLS/GnuTLS.chs" #-}

foreign import ccall "replace_transport_stable_ptrs"
  replace_transport_stable_ptrs :: Ptr () -> StablePtr Transport -> StablePtr Transport -> IO ()



handle :: WriteAttr (Session t) Handle
handle = writeAttr ss
    where rf hdl buf len err       = (hGetBuf hdl buf (fromIntegral len)) `catch` ef err
          sf hdl buf len err       = (hPutBuf hdl buf (fromIntegral len) >> return len) `catch` ef err
          ef err _                 = do (Errno iv) <- getErrno; poke err iv; return (-1)
          ss (Session sfp sr) hdl  = do rf' <- newStablePtr $ rf hdl
                                        sf' <- newStablePtr $ sf hdl
                                        hSetBuffering hdl NoBuffering
                                        withForeignPtr sfp $ \p -> replace_transport_stable_ptrs p rf' sf'
                                        addRefFinalizer sr (hClose hdl)


--------------------------------------------------------------------------------
-----------------------------  Session Actions   -------------------------------
--------------------------------------------------------------------------------

-- | Terminates the current TLS connection, which has been succesfully established
-- with 'handshake'. Notifies the peer with an alert that the connection is closing.
bye :: Session t -> CloseRequest -> IO (())
bye a1 a2 =
  withSession a1 $ \a1' -> 
  let {a2' = enumCInt a2} in 
  bye'_ a1' a2' >>= \res ->
  throwGnutlsIf res >>= \res' ->
  return (res')
{-# LINE 309 "./Network/GnuTLS/GnuTLS.chs" #-}
-- | Perform a handshake with the peer and initialize a TLS\/SSL connection.
-- Note that after the handshake completes applications /must/ check 
-- whether a high enough level of confidentiality was established.
handshake :: Session t -> IO ()
handshake a1 =
  withSession a1 $ \a1' -> 
  handshake'_ a1' >>= \res ->
  throwGnutlsIf res >>= \res' ->
  return (res')
{-# LINE 313 "./Network/GnuTLS/GnuTLS.chs" #-}
-- | Tells the client that we want to renogotiate the handshake. If the function
-- succeeds then 'handshake' can be called again on the connection.
rehandshake :: Session Server -> IO ()
rehandshake a1 =
  withSession a1 $ \a1' -> 
  rehandshake'_ a1' >>= \res ->
  throwGnutlsIf res >>= \res' ->
  return (res')
{-# LINE 316 "./Network/GnuTLS/GnuTLS.chs" #-}

-- | Set the maximum size of a handshake request. Larger requests are ignored.
-- Defaults to 16kb which should be large enough.
setMaxHandshakePacketLength :: Session t -> Int -> IO ()
setMaxHandshakePacketLength a1 a2 =
  withSession a1 $ \a1' -> 
  let {a2' = fromIntegral a2} in 
  setMaxHandshakePacketLength'_ a1' a2' >>= \res ->
  return ()
{-# LINE 321 "./Network/GnuTLS/GnuTLS.chs" #-}

-- | Set whether we want to do client authentication.
clientCert :: WriteAttr (Session Server) CertificateRequest
clientCert = writeAttr p
    where p s v = withSession s $ \sp -> gnutls_certificate_server_set_request sp (enumCInt v)

--------------------------------------------------------------------------------
----------------------------  Session Getters   --------------------------------
--------------------------------------------------------------------------------
 
serverWantedAuth :: Session Client -> IO Bool
serverWantedAuth s = withSession s $ \sp -> do
  iv <- gnutls_certificate_client_get_request_status sp
  throwGnutlsIfNeg iv
  return (iv /= 0)

verifyPeer :: Session t -> IO [CertificateStatus]
verifyPeer ses = do 
  withSession ses $ \sp -> do
  alloca $ \stat -> do
  gnutls_certificate_verify_peers2 sp stat >>= throwGnutlsIf
  ci <- peekEnum stat
  return $ filter (\e -> fromEnum e .&. ci /= 0) [CertInvalid, CertRevoked, CertSignerNotFound, CertSignerNotCa]

-- | Test whether this session is a resumed one.
isResumed :: Session t -> IO (Bool)
isResumed a1 =
  withSession a1 $ \a1' -> 
  isResumed'_ a1' >>= \res ->
  let {res' = isNotZero res} in
  return (res')
{-# LINE 347 "./Network/GnuTLS/GnuTLS.chs" #-}

isNotZero :: CInt -> Bool
isNotZero 0 = False
isNotZero _ = True

-- | Return the value of the last alert received - undefined if no alert has been received.
getAlert :: Session t -> IO (AlertDescription)
getAlert a1 =
  withSession a1 $ \a1' -> 
  getAlert'_ a1' >>= \res ->
  let {res' = cintEnum res} in
  return (res')
{-# LINE 354 "./Network/GnuTLS/GnuTLS.chs" #-}
-- | Return the currently used cipher.
getCipher :: Session t -> IO (CipherAlgorithm)
getCipher a1 =
  withSession a1 $ \a1' -> 
  getCipher'_ a1' >>= \res ->
  let {res' = cintEnum res} in
  return (res')
{-# LINE 356 "./Network/GnuTLS/GnuTLS.chs" #-}
-- | Return the key exchange algorithm used in the last handshake.
getKx :: Session t -> IO (KxAlgorithm)
getKx a1 =
  withSession a1 $ \a1' -> 
  getKx'_ a1' >>= \res ->
  let {res' = cintEnum res} in
  return (res')
{-# LINE 358 "./Network/GnuTLS/GnuTLS.chs" #-}
-- | Return the mac algorithm currently used.
getMac :: Session t -> IO (MacAlgorithm)
getMac a1 =
  withSession a1 $ \a1' -> 
  getMac'_ a1' >>= \res ->
  let {res' = cintEnum res} in
  return (res')
{-# LINE 360 "./Network/GnuTLS/GnuTLS.chs" #-}
-- | Return the compression method currently used.
getCompression :: Session t -> IO (CompressionMethod)
getCompression a1 =
  withSession a1 $ \a1' -> 
  getCompression'_ a1' >>= \res ->
  let {res' = cintEnum res} in
  return (res')
{-# LINE 362 "./Network/GnuTLS/GnuTLS.chs" #-}
-- | Return the currently used certificate type.
getCertificateType :: Session t -> IO (CertificateType)
getCertificateType a1 =
  withSession a1 $ \a1' -> 
  getCertificateType'_ a1' >>= \res ->
  let {res' = cintEnum res} in
  return (res')
{-# LINE 364 "./Network/GnuTLS/GnuTLS.chs" #-}
-- | Return the currently used protocol version.
getProtocol :: Session t -> IO (Protocol)
getProtocol a1 =
  withSession a1 $ \a1' -> 
  getProtocol'_ a1' >>= \res ->
  let {res' = cintEnum res} in
  return (res')
{-# LINE 366 "./Network/GnuTLS/GnuTLS.chs" #-}

-- | Return type of credentials for the current authentication schema.
getCredentialsType :: Session t -> IO (CredentialsType)
getCredentialsType a1 =
  withSession a1 $ \a1' -> 
  getCredentialsType'_ a1' >>= \res ->
  let {res' = cintEnum res} in
  return (res')
{-# LINE 369 "./Network/GnuTLS/GnuTLS.chs" #-}

-- | Return the type of credentials used for authenticating the server. Available with GnuTLS 1.2.
getServerCredentialsType :: Session t -> IO (CredentialsType)
getServerCredentialsType a1 =
  withSession a1 $ \a1' -> 
  getServerCredentialsType'_ a1' >>= \res ->
  let {res' = cintEnum res} in
  return (res')
{-# LINE 373 "./Network/GnuTLS/GnuTLS.chs" #-}
-- | Return the type of credentials used for authenticating the client. Available with GnuTLS 1.2.
getClientCredentialsType :: Session t -> IO (CredentialsType)
getClientCredentialsType a1 =
  withSession a1 $ \a1' -> 
  getClientCredentialsType'_ a1' >>= \res ->
  let {res' = cintEnum res} in
  return (res')
{-# LINE 376 "./Network/GnuTLS/GnuTLS.chs" #-}

-- | Get the certificate chain of the peer. 
-- In the case of X509 will return DER encoded certificate list
-- beginning with the peers key and continuing in the issuer chain.
-- With OpenPGP a single key will be returned in the raw format.
getPeersCertificatesRaw :: Session t -> IO [(Ptr CChar,Int)]
getPeersCertificatesRaw ses = do
  withSession ses $ \sp ->
    alloca $ \lenp -> do
      res <- gnutls_certificate_get_peers sp lenp
      if res == nullPtr 
         then return []
         else do len <- peek lenp
                 peekDatumArray (fromIntegral len - 1) res

--------------------------------------------------------------------------------
----------------------------  Read/Write Data   --------------------------------
--------------------------------------------------------------------------------

tlsSend :: Session t -> Ptr a -> Int -> IO (Int)
tlsSend a1 a2 a3 =
  withSession a1 $ \a1' -> 
  let {a2' = castPtr a2} in 
  let {a3' = fromIntegral a3} in 
  tlsSend'_ a1' a2' a3' >>= \res ->
  throwGnutlsIfNeg res >>= \res' ->
  return (res')
{-# LINE 397 "./Network/GnuTLS/GnuTLS.chs" #-}

tlsSendString :: Session t -> String -> IO ()
tlsSendString ses str = withCStringLen str $ \(ptr,len) -> loop ptr len
    where loop ptr len = do r <- tlsSend ses ptr len
                            case len-r of
                              x | x > 0 -> loop (plusPtr ptr r) x
                                | True  -> return ()
  
tlsCheckPending :: Session t -> IO (Int)
tlsCheckPending a1 =
  withSession a1 $ \a1' -> 
  tlsCheckPending'_ a1' >>= \res ->
  let {res' = fromIntegral res} in
  return (res')
{-# LINE 407 "./Network/GnuTLS/GnuTLS.chs" #-}

tlsRecv :: Session t -> Ptr a -> Int -> IO (Int)
tlsRecv a1 a2 a3 =
  withSession a1 $ \a1' -> 
  let {a2' = castPtr a2} in 
  let {a3' = fromIntegral a3} in 
  tlsRecv'_ a1' a2' a3' >>= \res ->
  throwGnutlsIfNeg res >>= \res' ->
  return (res')
{-# LINE 410 "./Network/GnuTLS/GnuTLS.chs" #-}

tlsRecvString :: Session t -> IO String
tlsRecvString ses = allocaBytes 1024 $ \ptr -> do
  r <- tlsRecv ses ptr 1024
  peekCAStringLen (ptr,r)

--------------------------------------------------------------------------------
---------------------   Anonymous Server Credentials   -------------------------
--------------------------------------------------------------------------------

anonymousServerCredentials :: IO AnonymousServerCredentials
anonymousServerCredentials = alloca $ \ptr -> do
  gnutls_anon_allocate_server_credentials ptr >>= throwGnutlsIf
  raw<- peek ptr
  rc <- newRefCount $ gnutls_anon_free_server_credentials raw
  fp <- FC.newForeignPtr raw $ freeRef rc
  return $ ASC fp rc

foreign import ccall safe "TLS.h gnutls_anon_free_server_credentials"
  gnutls_anon_free_server_credentials :: Ptr () -> IO ()

foreign import ccall safe "TLS.h gnutls_anon_allocate_server_credentials" 
  gnutls_anon_allocate_server_credentials :: Ptr (Ptr ()) -> IO CInt

class SetDHParams a where setDHParams :: a -> DH -> IO ()
instance SetDHParams AnonymousServerCredentials where 
  setDHParams asc@(ASC _ rc) dh@(DH _ refc) =
      do gnutls_anon_set_server_dh_params asc dh
         allocRef refc
         addRefFinalizer rc $ freeRef refc

gnutls_anon_set_server_dh_params :: AnonymousServerCredentials -> DH -> IO ()
gnutls_anon_set_server_dh_params a1 a2 =
  withAnonymousServerCredentials a1 $ \a1' -> 
  withDH a2 $ \a2' -> 
  gnutls_anon_set_server_dh_params'_ a1' a2' >>= \res ->
  return ()
{-# LINE 443 "./Network/GnuTLS/GnuTLS.chs" #-}

--------------------------------------------------------------------------------
---------------------   Anonymous Client Credentials   -------------------------
--------------------------------------------------------------------------------

anonymousClientCredentials :: IO AnonymousClientCredentials
anonymousClientCredentials = alloca $ \ptr -> do
  gnutls_anon_allocate_client_credentials ptr >>= throwGnutlsIf
  raw<- peek ptr
  rc <- newRefCount $ gnutls_anon_free_client_credentials raw
  fp <- FC.newForeignPtr raw $ freeRef rc
  return $ ACC fp rc

foreign import ccall safe "TLS.h gnutls_anon_free_client_credentials"
  gnutls_anon_free_client_credentials :: Ptr () -> IO ()

foreign import ccall safe "TLS.h gnutls_anon_allocate_client_credentials" 
  gnutls_anon_allocate_client_credentials :: Ptr (Ptr ()) -> IO CInt

--------------------------------------------------------------------------------
-----------------------   Certificate Credentials   ----------------------------
--------------------------------------------------------------------------------

certificateCredentials :: IO CertificateCredentials
certificateCredentials = alloca $ \ptr -> do
  gnutls_certificate_allocate_credentials ptr >>= throwGnutlsIf
  raw<- peek ptr
  rc <- newRefCount $ gnutls_certificate_free_credentials raw
  fp <- FC.newForeignPtr raw $ freeRef rc
  return $ CC fp rc

foreign import ccall safe "TLS.h gnutls_certificate_free_credentials" 
  gnutls_certificate_free_credentials :: Ptr () -> IO ()

foreign import ccall safe "TLS.h gnutls_certificate_allocate_credentials" 
  gnutls_certificate_allocate_credentials :: Ptr (Ptr ()) -> IO CInt

freeKeys :: CertificateCredentials -> IO ()
freeKeys a1 =
  withCertificateCredentials a1 $ \a1' -> 
  freeKeys'_ a1' >>= \res ->
  return ()
{-# LINE 481 "./Network/GnuTLS/GnuTLS.chs" #-}
freeCas :: CertificateCredentials -> IO ()
freeCas a1 =
  withCertificateCredentials a1 $ \a1' -> 
  freeCas'_ a1' >>= \res ->
  return ()
{-# LINE 482 "./Network/GnuTLS/GnuTLS.chs" #-}
freeCaNames :: CertificateCredentials -> IO ()
freeCaNames a1 =
  withCertificateCredentials a1 $ \a1' -> 
  freeCaNames'_ a1' >>= \res ->
  return ()
{-# LINE 483 "./Network/GnuTLS/GnuTLS.chs" #-}
freeCrls :: CertificateCredentials -> IO ()
freeCrls a1 =
  withCertificateCredentials a1 $ \a1' -> 
  freeCrls'_ a1' >>= \res ->
  return ()
{-# LINE 484 "./Network/GnuTLS/GnuTLS.chs" #-}

instance SetDHParams CertificateCredentials where 
  setDHParams cc@(CC _ rc) dh@(DH _ refc) =
      do gnutls_certificate_set_dh_params cc dh
         allocRef refc
         addRefFinalizer rc $ freeRef refc

gnutls_certificate_set_dh_params :: CertificateCredentials -> DH -> IO ()
gnutls_certificate_set_dh_params a1 a2 =
  withCertificateCredentials a1 $ \a1' -> 
  withDH a2 $ \a2' -> 
  gnutls_certificate_set_dh_params'_ a1' a2' >>= \res ->
  return ()
{-# LINE 493 "./Network/GnuTLS/GnuTLS.chs" #-}

certificateTrustFile :: CertificateCredentials -> FilePath -> X509CertificateFormat -> IO (Int)
certificateTrustFile a1 a2 a3 =
  withCertificateCredentials a1 $ \a1' -> 
  withCAString a2 $ \a2' -> 
  let {a3' = enumCInt a3} in 
  certificateTrustFile'_ a1' a2' a3' >>= \res ->
  throwGnutlsIfNeg res >>= \res' ->
  return (res')
{-# LINE 499 "./Network/GnuTLS/GnuTLS.chs" #-}

certificateCrlFile :: CertificateCredentials -> FilePath -> X509CertificateFormat -> IO (Int)
certificateCrlFile a1 a2 a3 =
  withCertificateCredentials a1 $ \a1' -> 
  withCAString a2 $ \a2' -> 
  let {a3' = enumCInt a3} in 
  certificateCrlFile'_ a1' a2' a3' >>= \res ->
  throwGnutlsIfNeg res >>= \res' ->
  return (res')
{-# LINE 505 "./Network/GnuTLS/GnuTLS.chs" #-}

certificateKeyFile :: CertificateCredentials -> FilePath -> FilePath -> X509CertificateFormat -> IO (Int)
certificateKeyFile a1 a2 a3 a4 =
  withCertificateCredentials a1 $ \a1' -> 
  withCAString a2 $ \a2' -> 
  withCAString a3 $ \a3' -> 
  let {a4' = enumCInt a4} in 
  certificateKeyFile'_ a1' a2' a3' a4' >>= \res ->
  throwGnutlsIfNeg res >>= \res' ->
  return (res')
{-# LINE 512 "./Network/GnuTLS/GnuTLS.chs" #-}

{-
void        gnutls_certificate_set_rsa_export_params (gnutls_certificate_credentials_t res, gnutls_rsa_params_t rsa_params);
void        gnutls_certificate_set_verify_flags (gnutls_certificate_credentials_t res, unsigned int flags);
void        gnutls_certificate_set_verify_limits (gnutls_certificate_credentials_t res, unsigned int max_bits, unsigned int max_depth);

int         gnutls_certificate_set_x509_trust_mem (gnutls_certificate_credentials_t res, const gnutls_datum_t *CA, gnutls_x509_crt_fmt_t type);
int         gnutls_certificate_set_x509_trust (gnutls_certificate_credentials_t res, gnutls_x509_crt_t *ca_list, int ca_list_size);

int         gnutls_certificate_set_x509_crl_mem (gnutls_certificate_credentials_t res, const gnutls_datum_t *CRL, gnutls_x509_crt_fmt_t type);
int         gnutls_certificate_set_x509_crl (gnutls_certificate_credentials_t res, gnutls_x509_crl_t *crl_list, int crl_list_size);

int         gnutls_certificate_set_x509_key_mem (gnutls_certificate_credentials_t res, const gnutls_datum_t *CERT, const gnutls_datum_t *KEY, gnutls_x509_crt_fmt_t type);
int         gnutls_certificate_set_x509_key (gnutls_certificate_credentials_t res, gnutls_x509_crt_t *cert_list, int cert_list_size, gnutls_x509_privkey_t key);
-}

--------------------------------------------------------------------------------
-------------------------   DH and RSA Parameters   ----------------------------
--------------------------------------------------------------------------------

class CredParameter a where 
  -- | Generate a new key with the given number of bits.
  generate   :: a -> Int -> IO ()

newDH :: IO DH
newDH = alloca $ \ptr -> do
  gnutls_dh_params_init ptr >>= throwGnutlsIf
  raw<- peek ptr
  rc <- newRefCount (gnutls_dh_params_deinit raw)
  fp <- FC.newForeignPtr raw (freeRef rc)
  return $ DH fp rc

foreign import ccall safe "TLS.h gnutls_dh_params_deinit" gnutls_dh_params_deinit :: Ptr () -> IO ()
foreign import ccall safe "TLS.h gnutls_dh_params_init"   gnutls_dh_params_init :: Ptr (Ptr ()) -> IO CInt

instance CredParameter DH where
  generate a i = withDH a (\ap -> gnutls_dh_params_generate2 ap (fromIntegral i) >>= throwGnutlsIf)

newRSA :: IO RSA
newRSA = alloca $ \ptr -> do
  gnutls_rsa_params_init ptr >>= throwGnutlsIf
  raw<- peek ptr
  rc <- newRefCount (gnutls_rsa_params_deinit raw)
  fp <- FC.newForeignPtr raw (freeRef rc)
  return $ RSA fp rc

foreign import ccall safe "TLS.h gnutls_rsa_params_deinit" gnutls_rsa_params_deinit :: Ptr () -> IO ()
foreign import ccall safe "TLS.h gnutls_rsa_params_init"   gnutls_rsa_params_init :: Ptr (Ptr ()) -> IO CInt

instance CredParameter RSA where
  generate a i = withRSA a (\ap -> gnutls_rsa_params_generate2 ap (fromIntegral i) >>= throwGnutlsIf)


--------------------------------------------------------------------------------
---------------------------   Miscellaneous   ----------------------------------
--------------------------------------------------------------------------------

-- | Return the cipher's key size in bytes.
cipherKeySize :: CipherAlgorithm -> Int
cipherKeySize a1 =
  let {a1' = enumCInt a1} in 
  let {res = cipherKeySize'_ a1'} in
  let {res' = fromIntegral res} in
  (res')
{-# LINE 572 "./Network/GnuTLS/GnuTLS.chs" #-}

-- | Return the name of the ciphersuite.
cipherSuiteName :: KxAlgorithm -> CipherAlgorithm -> MacAlgorithm -> String
cipherSuiteName a1 a2 a3 =
  unsafePerformIO $
  let {a1' = enumCInt a1} in 
  let {a2' = enumCInt a2} in 
  let {a3' = enumCInt a3} in 
  let {res = cipherSuiteName'_ a1' a2' a3'} in
  safePeekCString res >>= \res' ->
  return (res')
{-# LINE 579 "./Network/GnuTLS/GnuTLS.chs" #-}

-- | The version of /Gnutls/ used.
version = unsafePerformIO $ gnutls_check_version nullPtr >>= safePeekCString

{-# NOINLINE gnutlsGlobalInitIORef #-}
gnutlsGlobalInitIORef = unsafePerformIO $ do
  gcry_init_helper
  gnutls_global_init >>= throwGnutlsIf
  newIORef ()

gnutlsGlobalInit = readIORef gnutlsGlobalInitIORef

foreign import ccall unsafe "gcry_init_helper" gcry_init_helper :: IO ()


foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_alert_get_name"
  gnutlsAlertGetName'_ :: (CInt -> (IO (Ptr CChar)))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_cipher_get_name"
  gnutlsCipherGetName'_ :: (CInt -> (IO (Ptr CChar)))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_mac_get_name"
  gnutlsMacGetName'_ :: (CInt -> (IO (Ptr CChar)))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_compression_get_name"
  gnutlsCompressionGetName'_ :: (CInt -> (IO (Ptr CChar)))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_kx_get_name"
  gnutlsKxGetName'_ :: (CInt -> (IO (Ptr CChar)))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_certificate_type_get_name"
  gnutlsCertificateTypeGetName'_ :: (CInt -> (IO (Ptr CChar)))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_protocol_get_name"
  gnutlsProtocolGetName'_ :: (CInt -> (IO (Ptr CChar)))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_pk_algorithm_get_name"
  gnutlsPkAlgorithmGetName'_ :: (CInt -> (IO (Ptr CChar)))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_sign_algorithm_get_name"
  gnutlsSignAlgorithmGetName'_ :: (CInt -> (IO (Ptr CChar)))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_cipher_set_priority"
  gnutls_cipher_set_priority :: ((Ptr ()) -> ((Ptr CInt) -> (IO CInt)))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_mac_set_priority"
  gnutls_mac_set_priority :: ((Ptr ()) -> ((Ptr CInt) -> (IO CInt)))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_compression_set_priority"
  gnutls_compression_set_priority :: ((Ptr ()) -> ((Ptr CInt) -> (IO CInt)))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_kx_set_priority"
  gnutls_kx_set_priority :: ((Ptr ()) -> ((Ptr CInt) -> (IO CInt)))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_protocol_set_priority"
  gnutls_protocol_set_priority :: ((Ptr ()) -> ((Ptr CInt) -> (IO CInt)))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_certificate_type_set_priority"
  gnutls_certificate_type_set_priority :: ((Ptr ()) -> ((Ptr CInt) -> (IO CInt)))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_set_default_priority"
  setDefaultPriority'_ :: ((Ptr ()) -> (IO CInt))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_set_default_export_priority"
  setDefaultExportPriority'_ :: ((Ptr ()) -> (IO CInt))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_credentials_set"
  gnutls_credentials_set :: ((Ptr ()) -> (CInt -> ((Ptr ()) -> (IO CInt))))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_credentials_clear"
  gnutls_credentials_clear :: ((Ptr ()) -> (IO ()))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_dh_get_prime_bits"
  gnutls_dh_get_prime_bits :: ((Ptr ()) -> (IO CInt))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_dh_set_prime_bits"
  gnutls_dh_set_prime_bits :: ((Ptr ()) -> (CUInt -> (IO ())))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_transport_get_ptr2"
  gnutls_transport_get_ptr2'_ :: ((Ptr ()) -> ((Ptr (Ptr ())) -> ((Ptr (Ptr ())) -> (IO ()))))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_bye"
  bye'_ :: ((Ptr ()) -> (CInt -> (IO CInt)))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_handshake"
  handshake'_ :: ((Ptr ()) -> (IO CInt))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_rehandshake"
  rehandshake'_ :: ((Ptr ()) -> (IO CInt))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_handshake_set_max_packet_length"
  setMaxHandshakePacketLength'_ :: ((Ptr ()) -> (CUInt -> (IO ())))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_certificate_server_set_request"
  gnutls_certificate_server_set_request :: ((Ptr ()) -> (CInt -> (IO ())))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_certificate_client_get_request_status"
  gnutls_certificate_client_get_request_status :: ((Ptr ()) -> (IO CInt))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_certificate_verify_peers2"
  gnutls_certificate_verify_peers2 :: ((Ptr ()) -> ((Ptr CUInt) -> (IO CInt)))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_session_is_resumed"
  isResumed'_ :: ((Ptr ()) -> (IO CInt))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_alert_get"
  getAlert'_ :: ((Ptr ()) -> (IO CInt))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_cipher_get"
  getCipher'_ :: ((Ptr ()) -> (IO CInt))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_kx_get"
  getKx'_ :: ((Ptr ()) -> (IO CInt))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_mac_get"
  getMac'_ :: ((Ptr ()) -> (IO CInt))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_compression_get"
  getCompression'_ :: ((Ptr ()) -> (IO CInt))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_certificate_type_get"
  getCertificateType'_ :: ((Ptr ()) -> (IO CInt))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_protocol_get_version"
  getProtocol'_ :: ((Ptr ()) -> (IO CInt))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_auth_get_type"
  getCredentialsType'_ :: ((Ptr ()) -> (IO CInt))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_auth_server_get_type"
  getServerCredentialsType'_ :: ((Ptr ()) -> (IO CInt))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_auth_client_get_type"
  getClientCredentialsType'_ :: ((Ptr ()) -> (IO CInt))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_certificate_get_peers"
  gnutls_certificate_get_peers :: ((Ptr ()) -> ((Ptr CUInt) -> (IO (Ptr ()))))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_record_send"
  tlsSend'_ :: ((Ptr ()) -> ((Ptr ()) -> (CUInt -> (IO CInt))))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_record_check_pending"
  tlsCheckPending'_ :: ((Ptr ()) -> (IO CUInt))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_record_recv"
  tlsRecv'_ :: ((Ptr ()) -> ((Ptr ()) -> (CUInt -> (IO CInt))))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_anon_set_server_dh_params"
  gnutls_anon_set_server_dh_params'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO ())))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_certificate_free_keys"
  freeKeys'_ :: ((Ptr ()) -> (IO ()))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_certificate_free_cas"
  freeCas'_ :: ((Ptr ()) -> (IO ()))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_certificate_free_ca_names"
  freeCaNames'_ :: ((Ptr ()) -> (IO ()))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_certificate_free_crls"
  freeCrls'_ :: ((Ptr ()) -> (IO ()))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_certificate_set_dh_params"
  gnutls_certificate_set_dh_params'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO ())))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_certificate_set_x509_trust_file"
  certificateTrustFile'_ :: ((Ptr ()) -> ((Ptr CChar) -> (CInt -> (IO CInt))))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_certificate_set_x509_crl_file"
  certificateCrlFile'_ :: ((Ptr ()) -> ((Ptr CChar) -> (CInt -> (IO CInt))))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_certificate_set_x509_key_file"
  certificateKeyFile'_ :: ((Ptr ()) -> ((Ptr CChar) -> ((Ptr CChar) -> (CInt -> (IO CInt)))))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_dh_params_generate2"
  gnutls_dh_params_generate2 :: ((Ptr ()) -> (CUInt -> (IO CInt)))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_rsa_params_generate2"
  gnutls_rsa_params_generate2 :: ((Ptr ()) -> (CUInt -> (IO CInt)))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_cipher_get_key_size"
  cipherKeySize'_ :: (CInt -> CUInt)

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_cipher_suite_get_name"
  cipherSuiteName'_ :: (CInt -> (CInt -> (CInt -> (Ptr CChar))))

foreign import ccall safe "Network/GnuTLS/GnuTLS.chs.h gnutls_check_version"
  gnutls_check_version :: ((Ptr CChar) -> (IO (Ptr CChar)))

foreign import ccall unsafe "Network/GnuTLS/GnuTLS.chs.h gnutls_global_init"
  gnutls_global_init :: (IO CInt)