packages feed

keep-alive (empty) → 0.1.0.0

raw patch · 9 files changed

+361/−0 lines, 9 filesdep +basedep +keep-alivesetup-changed

Dependencies added: base, keep-alive

Files

+ ChangeLog.md view
@@ -0,0 +1,3 @@+# Changelog for keep-alive++## Unreleased changes
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Kyriakos Papachrysanthou (c) 2020++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Author name here nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,25 @@+# keep-alive++This module allows you to set per-connection keep alive parameters on windows and linux enviroments.+For more information on keep alive signals see <https://en.wikipedia.org/wiki/Keepalive>.+See also <https://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/> for a linux specific implementation.++The module is meant to be used in conjuction with the "network" package. However, in order to ensure adaptability, all functions require+a socket file descriptor instead of an implementation dependent socket type. For the network package, such a  descriptor can be obtained+with the withFdSocket function:++```hs+ -- sock is a Socket type+ withFdSocket sock $ \fd -> do+    before <- getKeepAliveOnOff fd+    print before -- False+    -- set keep alive on, idle 60 seconds, interval 2 seconds+    rlt <- setKeepAlive fd $ KeepAlive True 60 2+    case rlt of+        Left err -> print err+        Right () -> return ()+    after <- getKeepAliveOnOff fd+    print after -- True+```++Please note that only the envocing process can manipulate sockets based on their file descriptors.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ cbits/Cka.c view
@@ -0,0 +1,3 @@+#define INLINE+#include "CKa.h"+
+ keep-alive.cabal view
@@ -0,0 +1,60 @@+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.33.0.+--+-- see: https://github.com/sol/hpack+--+-- hash: e4fadd87f6fc7f6bca702c40ec776acd3dc1b4562423d193979808778831f6b8++name:           keep-alive+version:        0.1.0.0+homepage:       https://github.com/3kyro/keep-alive#readme+bug-reports:    https://github.com/3kyro/keep-alive/issues+author:         Kyriakos Papachrysanthou+maintainer:     papachrysanthou.k@gmail.com+copyright:      2020 Kyriakos Papachrysanthou+license:        BSD3+license-file:   LICENSE+build-type:     Simple+synopsis:       TCP keep alive implementation+category:       Network+description:+    This module allows you to set per-connection keep alive parameters on windows and linux enviroments.+    For more information on keep alive signals see <https://en.wikipedia.org/wiki/Keepalive>.+    See also <https://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/> for a linux specific implementation.++extra-source-files:+    README.md+    ChangeLog.md++source-repository head+  type: git+  location: https://github.com/3kyro/keep-alive++library+  exposed-modules:+      Network.Socket.KeepAlive+  other-modules:+      LibForeign+      Paths_keep_alive+  hs-source-dirs:+      src+  build-depends:+      base >=4.7 && <5+  include-dirs:+      cbits/+  c-sources: cbits/Cka.c+  default-language: Haskell2010++test-suite keep-alive-test+  type: exitcode-stdio-1.0+  main-is: Spec.hs+  other-modules:+      Paths_keep_alive+  hs-source-dirs:+      test+  ghc-options: -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      base >=4.7 && <5+    , keep-alive+  default-language: Haskell2010
+ src/LibForeign.hsc view
@@ -0,0 +1,116 @@+{-# LANGUAGE CPP,  ForeignFunctionInterface #-}+module LibForeign where++import Foreign+import Foreign.C.Types+import Foreign.C.Error+import Data.Word (Word32)++-- Platform specific includes+#ifdef _WIN32 ++# include "CKa.h"++#else++#include <netinet/tcp.h>++#endif+++getKeepAliveOnOff_ :: CInt -> IO CInt+getKeepAliveOnOff_ fd =+    alloca $ \ptr -> do+            let sz = fromIntegral $ sizeOf ( undefined :: CInt)+            with sz $ \ptr_sz -> do+                c_getsockopt fd c_SOL_SOCKET c_SO_KEEPALIVE ptr ptr_sz+                peek ptr++#ifdef _WIN32++setKeepAlive_ :: CInt -> Word32 -> Word32 -> Word32 -> IO CInt+setKeepAlive_ fd onoff idle intvl =+    c_winSetKeepAlive fd (fromIntegral onoff) (fromIntegral $ idle * 1000) (fromIntegral $ intvl * 1000)++#else++setKeepAlive_ :: CInt -> Word32 -> Word32 -> Word32 -> IO CInt+setKeepAlive_ fd onoff idle intvl = do++    let intOnOff = fromInteger $ toInteger onoff+    let intIdle = fromInteger $ toInteger idle+    let intIntvl = fromInteger $ toInteger intvl++    onoffrtn <- setKeepAliveOption_ fd c_SOL_SOCKET c_SO_KEEPALIVE intOnOff+    idlertn <- setKeepAliveOption_ fd c_SOL_TCP c_TCP_KEEPIDLE intIdle+    intrtn <- setKeepAliveOption_ fd c_SOL_TCP c_TCP_KEEPINTVL intIntvl++    -- Error check+    Errno rtn <-+        if onoffrtn + idlertn + intrtn /= 0+        then getErrno+        else return $ Errno 0+    return rtn++getKeepAliveOption_ :: CInt -> CInt -> CInt -> IO Int+getKeepAliveOption_ fd level option =+    alloca $ \ptr -> do+        let sz = fromIntegral $ sizeOf ( undefined :: CInt)+        with sz $ \ptr_sz -> do+            c_getsockopt fd level option ptr ptr_sz+            peek ptr++setKeepAliveOption_ :: CInt -> CInt -> CInt -> CInt -> IO CInt+setKeepAliveOption_ fd level option value = do+    let sz = fromIntegral $ sizeOf ( undefined :: Int)+    with value $ \ptr ->+        c_setsockopt fd level option ptr sz+++#endif++c_SOL_SOCKET_ = #const SOL_SOCKET++c_SOL_SOCKET :: CInt+c_SOL_SOCKET = fromIntegral c_SOL_SOCKET_++c_SO_KEEPALIVE_ = #const SO_KEEPALIVE+ +c_SO_KEEPALIVE :: CInt+c_SO_KEEPALIVE = fromIntegral c_SO_KEEPALIVE_++#ifdef _WIN32++foreign import ccall unsafe "winSetKeepAlive"  +    c_winSetKeepAlive :: CInt -> CULong -> CULong -> CULong -> IO CInt         ++#else++c_SOL_TCP_ = #const SOL_TCP++c_SOL_TCP :: CInt+c_SOL_TCP = fromIntegral c_SOL_TCP_++c_TCP_KEEPIDLE_ = #const TCP_KEEPIDLE++c_TCP_KEEPIDLE :: CInt+c_TCP_KEEPIDLE = fromIntegral c_TCP_KEEPIDLE_ +++c_TCP_KEEPCNT_ = #const TCP_KEEPCNT ++c_TCP_KEEPCNT :: CInt+c_TCP_KEEPCNT = fromIntegral c_TCP_KEEPCNT_++c_TCP_KEEPINTVL_ = #const TCP_KEEPINTVL++c_TCP_KEEPINTVL :: CInt +c_TCP_KEEPINTVL = fromIntegral c_TCP_KEEPINTVL_ ++#endif++foreign import ccall unsafe "getsockopt"+  c_getsockopt :: CInt -> CInt -> CInt -> Ptr a -> Ptr CInt -> IO CInt   +foreign import ccall unsafe "setsockopt"+  c_setsockopt :: CInt -> CInt -> CInt -> Ptr a -> CInt -> IO CInt+
+ src/Network/Socket/KeepAlive.hs view
@@ -0,0 +1,120 @@+{-# LANGUAGE CPP #-}++-----------------------------------------------------------------------------+-- |+-- This module allows you to set per-connection keep alive parameters on windows and linux enviroments.+-- For more information on keep alive signals see https://en.wikipedia.org/wiki/Keepalive.+-- See also https://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/ for a linux specific implementation.+--+-- The module is meant to be used in conjuction with the "network" package. However, in order to ensure adaptability, all functions require+-- a socket file descriptor instead of an implementation dependent socket type. For the network package, such a  descriptor can be obtained+-- with the withFdSocket function:+--+-- > -- sock is a Socket type+-- > withFdSocket sock $ \fd -> do+-- >    before <- getKeepAliveOnOff fd+-- >    print before -- False+-- >    -- set keep alive on, idle 60 seconds, interval 2 seconds+-- >    rlt <- setKeepAlive fd $ KeepAlive True 60 2+-- >    case rlt of+-- >        Left err -> print err+-- >        Right () -> return ()+-- >    after <- getKeepAliveOnOff fd+-- >    print after -- True+--+-- Please note that only the envocing process can manipulate sockets based on their file descriptors.++module Network.Socket.KeepAlive+    ( KeepAlive (..)+    , KeepAliveError (..)+    , setKeepAlive+    , getKeepAliveOnOff+    ) where++import           Data.Word  (Word32)+import           Foreign+import           Foreign.C+import           LibForeign+++-- | The main data structure defining keep alive parameters+data KeepAlive = KeepAlive+    { kaOnOff :: Bool+    -- ^ Turns on / off keep alive probes+    , kaIdle  :: Word32+    -- ^ The interval in seconds between the last data packet sent and the first keep alive probe+    , kaIntvl :: Word32+    -- ^ The interval in seconds between subsequential keepalive probes+    }+    deriving (Show, Eq, Ord)++-- | Errors starting with WSA are windows specific+data KeepAliveError = WSA_IO_PENDING+    | WSA_OPERATION_ABORTED+    | WSAEFAULT+    | WSAEINPROGRESS+    | WSAEINTR+    | WSAEINVAL+    | WSAENETDOWN+    | WSAENOPROTOOPT+    | WSAENOTSOCK+    | WSAEOPNOTSUPP+    | EBADF+    | EDOM+    | EINVAL+    | EISCONN+    | ENOPROTOOPT+    | ENOTSOCK+    | ENOMEM+    | ENOBUFS+    | OTHER_KEEPALIVE_ERROR+    deriving (Show, Eq, Ord)++-- | Set keep alive parameters for the current socket+setKeepAlive ::+    CInt+    -- ^ Socket file descriptor+    -> KeepAlive+    -- ^ Keep alive parameters+    -> IO ( Either KeepAliveError ())+setKeepAlive fd (KeepAlive onoff idle intvl) = do+    rlt <- setKeepAlive_ fd (cFromBool onoff) idle intvl+    return $ case rlt of+        0     -> Right ()+        997   -> Left WSA_IO_PENDING+        995   -> Left WSA_OPERATION_ABORTED+        10014 -> Left WSAEFAULT+        10036 -> Left WSAEINPROGRESS+        10004 -> Left WSAEINTR+        10022 -> Left WSAEINVAL+        10050 -> Left WSAENETDOWN+        10042 -> Left WSAENOPROTOOPT+        10038 -> Left WSAENOTSOCK+        10045 -> Left WSAEOPNOTSUPP+        9     -> Left EBADF+        33    -> Left EDOM+        22    -> Left EINVAL+        106   -> Left EISCONN+        92    -> Left ENOPROTOOPT+        88    -> Left ENOTSOCK+        12    -> Left ENOMEM+        105   -> Left ENOBUFS+        _     -> Left OTHER_KEEPALIVE_ERROR++-- | Returns True if keep alive is active for the specified socket+getKeepAliveOnOff ::+    CInt+    -- ^ Socket file descriptor+    -> IO Bool+getKeepAliveOnOff fd =+    cToBool . fromInteger . toInteger <$> getKeepAliveOnOff_ fd++cToBool :: Int -> Bool+cToBool x+    | x == 0 = False+    | otherwise = True++cFromBool :: Bool -> Word32+cFromBool True  = 1+cFromBool False = 0+
+ test/Spec.hs view
@@ -0,0 +1,2 @@+main :: IO ()+main = putStrLn "Test suite not yet implemented"