Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 34 additions & 12 deletions Network/Socket/Options.hsc
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,12 @@ import Foreign.C.Types
import Foreign.Marshal.Alloc (alloca)
import Foreign.Ptr (Ptr)
import Foreign.Storable (peek)
import Network.Socket (Socket, SocketType(..), fdSocket)
import Network.Socket (Socket, SocketType(..))
##if MIN_VERSION_network(3,1,0)
import Network.Socket (withFdSocket)
##else
import Network.Socket (fdSocket)
##endif
import Network.Socket.Internal (throwSocketErrorIfMinus1_)
import System.Posix.Types (Fd(Fd))

Expand All @@ -90,17 +95,27 @@ import GHC.IO.Handle.Types (Handle__(Handle__, haDevice))
-- | The getters and setters in this module can be used not only on 'Socket's,
-- but on raw 'Fd's (file descriptors) as well.
class HasSocket a where
getSocket :: a -> CInt
withFdSocket_ :: a -> (CInt -> IO b) -> IO b

instance HasSocket Fd where
getSocket (Fd n) = n
withFdSocket_ (Fd n) action = action n

instance HasSocket Socket where
getSocket = fdSocket
##if MIN_VERSION_network(3,1,0)
withFdSocket_ = withFdSocket
##else
##if MIN_VERSION_network(3,0,0)
withFdSocket_ sock action = do
fd <- fdSocket sock
action fd
##else
withFdSocket_ sock action = action (fdSocket sock)
##endif
##endif

##ifdef __GLASGOW_HASKELL__
instance HasSocket FD.FD where
getSocket = FD.fdFD
withFdSocket_ s action = action (FD.fdFD s)
##endif

type Seconds = Int
Expand Down Expand Up @@ -148,7 +163,8 @@ getLinger sock =
alloca $ \l_onoff_ptr ->
alloca $ \l_linger_ptr -> do
throwSocketErrorIfMinus1_ "getsockopt" $
c_getsockopt_linger (getSocket sock) l_onoff_ptr l_linger_ptr
withFdSocket_ sock $ \sockFd ->
c_getsockopt_linger sockFd l_onoff_ptr l_linger_ptr
onoff <- peek l_onoff_ptr
if onoff /= 0
then (Just . fromIntegral) `fmap` peek l_linger_ptr
Expand Down Expand Up @@ -220,10 +236,12 @@ setKeepAlive = setBool #{const SOL_SOCKET} #{const SO_KEEPALIVE}
setLinger :: HasSocket sock => sock -> Maybe Seconds -> IO ()
setLinger sock (Just linger) =
throwSocketErrorIfMinus1_ "setsockopt" $
c_setsockopt_linger (getSocket sock) 1 (fromIntegral linger)
withFdSocket_ sock $ \sockFd ->
c_setsockopt_linger sockFd 1 (fromIntegral linger)
setLinger sock Nothing =
throwSocketErrorIfMinus1_ "setsockopt" $
c_setsockopt_linger (getSocket sock) 0 0
withFdSocket_ sock $ \sockFd ->
c_setsockopt_linger sockFd 0 0

setOOBInline :: HasSocket sock => sock -> Bool -> IO ()
setOOBInline = setBool #{const SOL_SOCKET} #{const SO_OOBINLINE}
Expand Down Expand Up @@ -280,25 +298,29 @@ getCInt :: HasSocket sock => Level -> OptName -> sock -> IO CInt
getCInt level optname sock =
alloca $ \ptr -> do
throwSocketErrorIfMinus1_ "getsockopt" $
c_getsockopt_int (getSocket sock) level optname ptr
withFdSocket_ sock $ \sockFd ->
c_getsockopt_int sockFd level optname ptr
peek ptr

setCInt :: HasSocket sock => Level -> OptName -> sock -> CInt -> IO ()
setCInt level optname sock n =
throwSocketErrorIfMinus1_ "setsockopt" $
c_setsockopt_int (getSocket sock) level optname n
withFdSocket_ sock $ \sockFd ->
c_setsockopt_int sockFd level optname n

getTime :: HasSocket sock => Level -> OptName -> sock -> IO Microseconds
getTime level optname sock =
alloca $ \ptr -> do
throwSocketErrorIfMinus1_ "getsockopt" $
c_getsockopt_time (getSocket sock) level optname ptr
withFdSocket_ sock $ \sockFd ->
c_getsockopt_time sockFd level optname ptr
peek ptr

setTime :: HasSocket sock => Level -> OptName -> sock -> Microseconds -> IO ()
setTime level optname sock usec =
throwSocketErrorIfMinus1_ "setsockopt" $
c_setsockopt_time (getSocket sock) level optname usec
withFdSocket_ sock $ \sockFd ->
c_setsockopt_time sockFd level optname usec

foreign import ccall
c_getsockopt_int :: SockFd -> Level -> OptName -> Ptr CInt -> IO CInt
Expand Down