module Network.Socket.SendFile.Internal (
sendFile,
sendFile',
sendFileMode,
unsafeSendFile,
unsafeSendFile',
) where
#if defined(PORTABLE_SENDFILE)
import Data.ByteString.Char8 (hGet, hPutStr, length, ByteString)
import Network.Socket.ByteString (sendAll)
import Network.Socket (Socket(..))
import Prelude hiding (length)
import System.IO (Handle, IOMode(..), SeekMode(..), hFileSize, hFlush, hSeek, withBinaryFile)
#else
import GHC.Handle (withHandle_)
import GHC.IOBase (haFD)
import Network.Socket (Socket(..), fdSocket)
import System.IO (Handle, IOMode(..), hFileSize, hFlush, withBinaryFile)
import System.Posix.Types (Fd(..))
#endif
#if defined(WIN32_SENDFILE)
import Network.Socket.SendFile.Win32 (_sendFile)
sendFileMode :: String
sendFileMode = "WIN32_SENDFILE"
#endif
#if defined(LINUX_SENDFILE)
import Network.Socket.SendFile.Linux (_sendFile)
sendFileMode :: String
sendFileMode = "LINUX_SENDFILE"
#endif
#if defined(FREEBSD_SENDFILE)
import Network.Socket.SendFile.FreeBSD (_sendFile)
sendFileMode :: String
sendFileMode = "FREEBSD_SENDFILE"
#endif
#if defined(PORTABLE_SENDFILE)
sendFileMode :: String
sendFileMode = "PORTABLE_SENDFILE"
sendFile' :: Socket -> Handle -> Integer -> Integer -> IO ()
sendFile' = wrapSendFile' $ \outs inp off count -> do
hSeek inp AbsoluteSeek off
rsend (sendAll outs) inp count
unsafeSendFile' :: Handle -> Handle -> Integer -> Integer -> IO ()
unsafeSendFile' = wrapSendFile' $ \outp inp off count -> do
hSeek inp AbsoluteSeek off
rsend (hPutStr outp) inp count
hFlush outp
rsend :: (ByteString -> IO ()) -> Handle -> Integer -> IO ()
rsend write inp n = do
loop n
where
loop 0 = return ()
loop reqBytes = do
let bytes = min 32768 reqBytes :: Integer
buf <- hGet inp (fromIntegral bytes)
write buf
loop $ reqBytes (fromIntegral $ length buf)
#else
sendFile' :: Socket -> Handle -> Integer -> Integer -> IO ()
sendFile' outs inp off count =
withHandle_ "Network.Socket.SendFile.sendFile'" inp $ \inp' -> do
let out_fd = Fd (fdSocket outs)
let in_fd = Fd (haFD inp')
wrapSendFile' _sendFile out_fd in_fd off count
unsafeSendFile' :: Handle -> Handle -> Integer -> Integer -> IO ()
unsafeSendFile' outp inp off count = do
hFlush outp
withHandle_ "Network.Socket.SendFile.unsafeSendFile'" outp $ \outp' -> do
withHandle_ "Network.Socket.SendFile.unsafeSendFile'" inp $ \inp' -> do
let out_fd = Fd (haFD outp')
let in_fd = Fd (haFD inp')
wrapSendFile' _sendFile out_fd in_fd off count
#endif
sendFile :: Socket -> FilePath -> IO ()
sendFile outs infp = withBinaryFile infp ReadMode $ \inp -> do
count <- hFileSize inp
sendFile' outs inp 0 count
unsafeSendFile :: Handle -> FilePath -> IO ()
unsafeSendFile outp infp = withBinaryFile infp ReadMode $ \inp -> do
count <- hFileSize inp
unsafeSendFile' outp inp 0 count
wrapSendFile' :: Integral i => (a -> b -> i -> i -> IO ()) -> a -> b -> Integer -> Integer -> IO ()
wrapSendFile' fun outp inp off count
| off < 0 = error "SendFile - offset must be a positive integer"
| count < 0 = error "SendFile - count must be a positive integer"
| count == 0 = return ()
| otherwise = fun outp inp (fromIntegral off) (fromIntegral count)