simple-sendfile-0.0.0: Network/Sendfile/MacOS.hsc
{-# LANGUAGE ForeignFunctionInterface #-}
module Network.Sendfile.MacOS (sendfile) where
import Control.Concurrent
import Control.Exception
import Control.Monad
import Data.Int (Int64)
import Foreign.C.Error (eAGAIN, eINTR, getErrno, throwErrno)
import Foreign.C.Types (CInt)
import Foreign.Marshal (alloca)
import Foreign.Ptr (Ptr, nullPtr)
import Foreign.Storable (peek, poke)
import Network.Sendfile.Types
import Network.Socket
import System.Posix.IO
import System.Posix.Types (Fd(..))
{-|
Simple binding for sendfile() of MacOS.
- Used system calls: open(), sendfile(), and close().
-}
sendfile :: Socket -> FilePath -> FileRange -> IO ()
sendfile sock path range = bracket
(openFd path ReadOnly Nothing defaultFileFlags)
closeFd
sendfile'
where
dst = Fd $ fdSocket sock
sendfile' fd = alloca $ \lenp -> do
case range of
EntireFile -> do
poke lenp 0
sendEntire dst fd 0 lenp
PartOfFile off len -> do
let off' = fromInteger off
poke lenp (fromInteger len)
sendPart dst fd off' lenp
sendEntire :: Fd -> Fd -> (#type off_t) -> Ptr (#type off_t) -> IO ()
sendEntire dst src off lenp = do
do rc <- c_sendfile src dst off lenp
when (rc /= 0) $ do
errno <- getErrno
if errno == eAGAIN || errno == eINTR
then do
sent <- peek lenp
poke lenp 0
threadWaitWrite dst
sendEntire dst src (off + sent) lenp
else throwErrno "Network.SendFile.MacOS.sendEntire"
sendPart :: Fd -> Fd -> (#type off_t) -> Ptr (#type off_t) -> IO ()
sendPart dst src off lenp = do
do len <- peek lenp
rc <- c_sendfile src dst off lenp
when (rc /= 0) $ do
errno <- getErrno
if errno == eAGAIN || errno == eINTR
then do
sent <- peek lenp
poke lenp (len - sent)
threadWaitWrite dst
sendPart dst src (off + sent) lenp
else throwErrno "Network.SendFile.MacOS.sendPart"
c_sendfile :: Fd -> Fd -> (#type off_t) -> Ptr (#type off_t) -> IO CInt
c_sendfile fd s offset lenp = c_sendfile' fd s offset lenp nullPtr 0
foreign import ccall unsafe "sys/uio.h sendfile" c_sendfile'
:: Fd -> Fd -> (#type off_t) -> Ptr (#type off_t) -> Ptr () -> CInt -> IO CInt