{-# LANGUAGE CPP, RecordWildCards #-} module Network.Socket.SendFile.Internal ( sendFile, sendFileIterWith, sendFile', sendFileIterWith', sendFile'', sendFileIterWith'', unsafeSendFile, unsafeSendFileIterWith, unsafeSendFile', unsafeSendFileIterWith', sendFileMode, ) where #if defined(PORTABLE_SENDFILE) import Network.Socket.SendFile.Portable (sendFileMode, sendFile'', sendFileIterWith'', unsafeSendFile'', unsafeSendFileIterWith'') #else import Network.Socket (fdSocket) import Network.Socket.SendFile.Util import System.Posix.Types (Fd(..)) #ifdef __GLASGOW_HASKELL__ #if __GLASGOW_HASKELL__ >= 611 import GHC.IO.Handle.Internals (withHandle_) import GHC.IO.Handle.Types (Handle__(..)) import qualified GHC.IO.FD as FD -- import qualified GHC.IO.Handle.FD as FD import GHC.IO.Exception import Data.Typeable (cast) #else import GHC.IOBase import GHC.Handle hiding (fdToHandle) import qualified GHC.Handle #endif #endif #endif import Network.Socket (Socket) import Network.Socket.SendFile.Iter (Iter(..)) import System.IO (Handle, IOMode(..), hFileSize, hFlush, withBinaryFile) #ifdef __GLASGOW_HASKELL__ #if __GLASGOW_HASKELL__ >= 611 import System.IO.Error #endif #endif #if defined(WIN32_SENDFILE) import Network.Socket.SendFile.Win32 (_sendFile, sendFileIter) sendFileMode :: String sendFileMode = "WIN32_SENDFILE" #endif #if defined(LINUX_SENDFILE) import Network.Socket.SendFile.Linux (_sendFile, sendFileIter) sendFileMode :: String sendFileMode = "LINUX_SENDFILE" #endif #if defined(FREEBSD_SENDFILE) import Network.Socket.SendFile.FreeBSD (_sendFile, sendFileIter) sendFileMode :: String sendFileMode = "FREEBSD_SENDFILE" #endif #if defined(DARWIN_SENDFILE) import Network.Socket.SendFile.Darwin (_sendFile, sendFileIter) sendFileMode :: String sendFileMode = "DARWIN_SENDFILE" #endif #if defined(PORTABLE_SENDFILE) #else sendFile'' :: Socket -> Handle -> Integer -> Integer -> IO () sendFile'' outs inh off count = do let out_fd = Fd (fdSocket outs) withFd inh $ \in_fd -> wrapSendFile' (\out_fd_ in_fd_ _blockSize_ off_ count_ -> _sendFile out_fd_ in_fd_ off_ count_) out_fd in_fd count off count sendFileIterWith'' :: (IO Iter -> IO a) -> Socket -> Handle -> Integer -> Integer -> Integer -> IO a sendFileIterWith'' stepper outs inp blockSize off count = do let out_fd = Fd (fdSocket outs) withFd inp $ \in_fd -> stepper $ wrapSendFile' sendFileIter out_fd in_fd blockSize off count unsafeSendFile'' :: Handle -> Handle -> Integer -> Integer -> IO () unsafeSendFile'' outp inp off count = do hFlush outp withFd outp $ \out_fd -> withFd inp $ \in_fd -> wrapSendFile' (\out_fd_ in_fd_ _blockSize_ off_ count_ -> _sendFile out_fd_ in_fd_ off_ count_) out_fd in_fd count off count -- wrapSendFile' _sendFile out_fd in_fd off count unsafeSendFileIterWith'' :: (IO Iter -> IO a) -> Handle -> Handle -> Integer -> Integer -> Integer -> IO a unsafeSendFileIterWith'' stepper outp inp blockSize off count = do hFlush outp withFd outp $ \out_fd -> withFd inp $ \in_fd -> stepper $ wrapSendFile' sendFileIter out_fd in_fd blockSize off count -- The Fd should not be used after the action returns because the -- Handler may be garbage collected and than will cause the finalizer -- to close the fd. withFd :: Handle -> (Fd -> IO a) -> IO a #ifdef __GLASGOW_HASKELL__ #if __GLASGOW_HASKELL__ >= 611 withFd h f = withHandle_ "withFd" h $ \ Handle__{..} -> do case cast haDevice of Nothing -> ioError (ioeSetErrorString (mkIOError IllegalOperation "withFd" (Just h) Nothing) "handle is not a file descriptor") Just fd -> f (Fd (fromIntegral (FD.fdFD fd))) #else withFd h f = withHandle_ "withFd" h $ \ h_ -> f (Fd (fromIntegral (haFD h_))) #endif #endif #endif sendFile :: Socket -> FilePath -> IO () sendFile outs infp = withBinaryFile infp ReadMode $ \inp -> do count <- hFileSize inp sendFile'' outs inp 0 count sendFileIterWith :: (IO Iter -> IO a) -> Socket -> FilePath -> Integer -> IO a sendFileIterWith stepper outs infp blockSize = withBinaryFile infp ReadMode $ \inp -> do count <- hFileSize inp sendFileIterWith'' stepper outs inp blockSize 0 count sendFile' :: Socket -> FilePath -> Integer -> Integer -> IO () sendFile' outs infp offset count = withBinaryFile infp ReadMode $ \inp -> sendFile'' outs inp offset count sendFileIterWith' :: (IO Iter -> IO a) -> Socket -> FilePath -> Integer -> Integer -> Integer -> IO a sendFileIterWith' stepper outs infp blockSize offset count = withBinaryFile infp ReadMode $ \inp -> sendFileIterWith'' stepper outs inp blockSize offset count unsafeSendFile :: Handle -> FilePath -> IO () unsafeSendFile outp infp = withBinaryFile infp ReadMode $ \inp -> do count <- hFileSize inp unsafeSendFile'' outp inp 0 count unsafeSendFileIterWith :: (IO Iter -> IO a) -> Handle -> FilePath -> Integer -> IO a unsafeSendFileIterWith stepper outp infp blockSize = withBinaryFile infp ReadMode $ \inp -> do count <- hFileSize inp unsafeSendFileIterWith'' stepper outp inp blockSize 0 count unsafeSendFile' :: Handle -- ^ The output handle -> FilePath -- ^ The input filepath -> Integer -- ^ The offset to start at -> Integer -- ^ The number of bytes to send -> IO () unsafeSendFile' outp infp offset count = withBinaryFile infp ReadMode $ \inp -> do unsafeSendFile'' outp inp offset count unsafeSendFileIterWith' :: (IO Iter -> IO a) -> Handle -- ^ The output handle -> FilePath -- ^ The input filepath -> Integer -- ^ maximum block size -> Integer -- ^ The offset to start at -> Integer -- ^ The number of bytes to send -> IO a unsafeSendFileIterWith' stepper outp infp blockSize offset count = withBinaryFile infp ReadMode $ \inp -> do unsafeSendFileIterWith'' stepper outp inp blockSize offset count