    {-# LANGUAGE DeriveDataTypeable #-}
    -- |
    -- Module      : Network.Socks5.Types
    -- License     : BSD-style
    -- Maintainer  : Vincent Hanquez <vincent@snarc.org>
    -- Stability   : experimental
    -- Portability : unknown
    module Network.Socks5.Types
    	( SocksCommand(..)
    	, SocksMethod(..)
    	, SocksAddr(..)
    	, SocksReply(..)
    	, SocksVersionNotSupported(..)
    	, SocksError(..)
    	) where

    import Data.ByteString (ByteString)
    import Data.Word
    import Data.Data
    import Network.Socket (HostAddress, HostAddress6)
    import Control.Exception

    data SocksCommand =
    	  SocksCommandConnect
    	| SocksCommandBind
    	| SocksCommandUdpAssociate
    	| SocksCommandOther Word8
    	deriving (Show,Eq,Ord)

    data SocksMethod =
    	  SocksMethodNone
    	| SocksMethodGSSAPI
    	| SocksMethodUsernamePassword
    	| SocksMethodOther Word8
    	| SocksMethodNotAcceptable
    	deriving (Show,Eq,Ord)

    data SocksAddr =
    	  SocksAddrIPV4 HostAddress
    	| SocksAddrDomainName ByteString
    	| SocksAddrIPV6 HostAddress6
    	deriving (Show,Eq)

    data SocksReply =
    	  SocksReplySuccess
    	| SocksReplyGeneralServerFailure
    	| SocksReplyConnectionNotAllowedByRule
    	| SocksReplyNetworkUnreachable
    	| SocksReplyHostUnreachable
    	| SocksReplyConnectionRefused
    	| SocksReplyTTLExpired
    	| SocksReplyCommandNotSupported
    	| SocksReplyAddrTypeNotSupported
    	| SocksReplyOther Word8
    	deriving (Show,Eq,Ord,Data,Typeable)

    data SocksVersionNotSupported = SocksVersionNotSupported
    	deriving (Show,Data,Typeable)

    data SocksError = SocksError SocksReply
    	deriving (Show,Eq,Data,Typeable)

    instance Exception SocksError
    instance Exception SocksVersionNotSupported

    instance Enum SocksCommand where
    	toEnum 1 = SocksCommandConnect
    	toEnum 2 = SocksCommandBind
    	toEnum 3 = SocksCommandUdpAssociate
    	toEnum w
    		| w < 256   = SocksCommandOther $ fromIntegral w
    		| otherwise = error "socks command is only 8 bits"
    	fromEnum SocksCommandConnect      = 1
    	fromEnum SocksCommandBind         = 2
    	fromEnum SocksCommandUdpAssociate = 3
    	fromEnum (SocksCommandOther w)    = fromIntegral w

    instance Enum SocksMethod where
    	toEnum 0    = SocksMethodNone
    	toEnum 1    = SocksMethodGSSAPI
    	toEnum 2    = SocksMethodUsernamePassword
    	toEnum 0xff = SocksMethodNotAcceptable
    	toEnum w
    		| w < 256   = SocksMethodOther $ fromIntegral w
    		| otherwise = error "socks method is only 8 bits"
    	fromEnum SocksMethodNone             = 0
    	fromEnum SocksMethodGSSAPI           = 1
    	fromEnum SocksMethodUsernamePassword = 2
    	fromEnum (SocksMethodOther w)        = fromIntegral w
    	fromEnum SocksMethodNotAcceptable    = 0xff

    instance Enum SocksReply where
    	fromEnum SocksReplySuccess                    = 0
    	fromEnum SocksReplyGeneralServerFailure       = 1
    	fromEnum SocksReplyConnectionNotAllowedByRule = 2
    	fromEnum SocksReplyNetworkUnreachable         = 3
    	fromEnum SocksReplyHostUnreachable            = 4
    	fromEnum SocksReplyConnectionRefused          = 5
    	fromEnum SocksReplyTTLExpired                 = 6
    	fromEnum SocksReplyCommandNotSupported        = 7
    	fromEnum SocksReplyAddrTypeNotSupported       = 8
    	fromEnum (SocksReplyOther w)                  = fromIntegral w
    	toEnum 0 = SocksReplySuccess
    	toEnum 1 = SocksReplyGeneralServerFailure
    	toEnum 2 = SocksReplyConnectionNotAllowedByRule
    	toEnum 3 = SocksReplyNetworkUnreachable
    	toEnum 4 = SocksReplyHostUnreachable
    	toEnum 5 = SocksReplyConnectionRefused
    	toEnum 6 = SocksReplyTTLExpired
    	toEnum 7 = SocksReplyCommandNotSupported
    	toEnum 8 = SocksReplyAddrTypeNotSupported
    	toEnum w
    		| w < 256   = SocksReplyOther $ fromIntegral w
    		| otherwise = error "sock reply is only 8 bits"