libssh2-0.1: Network/SSH/Client/LibSSH2/Errors.chs
{-# LANGUAGE ForeignFunctionInterface, DeriveDataTypeable, FlexibleInstances, TypeFamilies, MultiParamTypeClasses #-}
#include <libssh2.h>
{# context lib="ssh2" prefix="libssh2" #}
module Network.SSH.Client.LibSSH2.Errors
(-- * Types
ErrorCode (..),
NULL_POINTER,
-- * Utilities
CIntResult (..),
-- * Functions
getLastError,
handleInt,
handleBool,
handleNullPtr,
int2error
) where
import Control.Exception
import Data.Generics
import Foreign
import Foreign.Ptr
import Foreign.C.Types
import Network.SSH.Client.LibSSH2.Types
-- | Error codes returned by libssh2.
data ErrorCode =
NONE
| SOCKET_NONE
| BANNER_RECV
| BANNER_SEND
| INVALID_MAC
| KEX_FALIURE
| ALLOC
| SOCKET_SEND
| KEY_EXCHANGE_FAILURE
| TIMEOUT
| HOSTKEY_INIT
| HOSTKEY_SIGN
| DECRYPT
| SOCKET_DISCONNECT
| PROTO
| PASSWORD_EXPIRED
| FILE
| METHOD_NONE
| AUTHENTICATION_FAILED
| PUBLICKEY_UNVERIFIED
| CHANNEL_OUTOFORDER
| CHANNEL_FAILURE
| CHANNEL_REQUEST_DENIED
| CHANNEL_UNKNOWN
| CHANNEL_WINDOW_EXCEEDED
| CHANNEL_PACKET_EXCEEDED
| CHANNEL_CLOSED
| CHANNEL_EOF_SENT
| SCP_PROTOCOL
| ZLIB
| SOCKET_TIMEOUT
| SFTP_PROTOCOL
| REQUEST_DENIED
| METHOD_NOT_SUPPORTED
| INVAL
| INVALID_POLL_TYPE
| PUBLICKEY_PROTOCOL
| EAGAIN
| BUFFER_TOO_SMALL
| BAD_USE
| COMPRESS
| OUT_OF_BOUNDARY
| AGENT_PROTOCOL
| SOCKET_RECV
| ENCRYPT
| BAD_SOCKET
deriving (Eq, Show, Ord, Enum, Data, Typeable)
instance Exception ErrorCode
error2int :: (Num i) => ErrorCode -> i
error2int = fromIntegral . negate . fromEnum
int2error :: (Integral i) => i -> ErrorCode
int2error = toEnum . negate . fromIntegral
-- | Exception to throw when null pointer received
-- from libssh2.
data NULL_POINTER = NULL_POINTER
deriving (Eq, Show, Data, Typeable)
instance Exception NULL_POINTER
class HasCInt a where
intResult :: a -> CInt
class (HasCInt a) => CIntResult a b where
fromCInt :: a -> b
instance HasCInt CInt where
intResult = id
instance (Num b) => CIntResult CInt b where
fromCInt = fromIntegral
instance HasCInt CLong where
intResult = fromIntegral
instance (Num b) => CIntResult CLong b where
fromCInt = fromIntegral
instance (Integral i) => HasCInt (i, a) where
intResult (i, _) = fromIntegral i
instance (Integral i, Num b) => CIntResult (i, a) (b, a) where
fromCInt (i, a) = (fromIntegral i, a)
instance HasCInt (CInt, a, b) where
intResult (i, _, _) = i
instance (Num j) => CIntResult (CInt, a, b) (j, a, b) where
fromCInt (i, a, b) = (fromIntegral i, a, b)
instance HasCInt (CInt, a, b, c) where
intResult (i, _, _, _) = i
instance (Num j) => CIntResult (CInt, a, b, c) (j, a, b, c) where
fromCInt (i, a, b, c) = (fromIntegral i, a, b, c)
{# fun session_last_error as getLastError_
{ toPointer `Session',
alloca- `String' peekCStringPtr*,
castPtr `Ptr Int',
`Int' } -> `Int' #}
-- | Get last error information.
getLastError :: Session -> IO (Int, String)
getLastError s = getLastError_ s nullPtr 0
-- | Throw an exception if negative value passed,
-- or return unchanged value.
handleInt :: (CIntResult a b) => a -> IO b
handleInt x =
let r = intResult x
in if r < 0
then throw (int2error r)
else return (fromCInt x)
handleBool :: CInt -> IO Bool
handleBool x
| x == 0 = return False
| x > 0 = return True
| otherwise = throw (int2error x)
-- | Throw an exception if null pointer passed,
-- or return it casted to right type.
handleNullPtr :: (IsPointer a) => Ptr () -> IO a
handleNullPtr p
| p == nullPtr = throw NULL_POINTER
| otherwise = return (fromPointer p)