diff --git a/csrc/sendfile_linux.c b/csrc/sendfile_linux.c
deleted file mode 100644
--- a/csrc/sendfile_linux.c
+++ /dev/null
@@ -1,9 +0,0 @@
-
-/* LINUX */
-#include <stdlib.h>
-#include <sys/sendfile.h>
-
-ssize_t c_sendfile_linux(const int out_fd, const int in_fd, const size_t count) {
-    return sendfile(out_fd, in_fd, NULL, count);
-}
-
diff --git a/csrc/sendfile_win32.c b/csrc/sendfile_win32.c
deleted file mode 100644
--- a/csrc/sendfile_win32.c
+++ /dev/null
@@ -1,16 +0,0 @@
-
-/* WIN32 */
-#include <windows.h>
-#include <mswsock.h>
-#include <io.h>
-
-BOOL c_TransmitFile(SOCKET out_fd, HANDLE in_hdl, DWORD count) {
-    /* http://msdn.microsoft.com/en-us/library/ms740565(VS.85).aspx */
-    return TransmitFile(out_fd, in_hdl, count, 0, NULL, NULL, TF_USE_KERNEL_APC);
-}
-
-long c_get_osfhandle(int fd) {
-    /* http://support.microsoft.com/kb/99173 - MAY BE IMPORTANT */
-    /* http://msdn.microsoft.com/en-us/library/ks2530z6.aspx */
-    return _get_osfhandle(fd);
-}
diff --git a/sendfile.cabal b/sendfile.cabal
--- a/sendfile.cabal
+++ b/sendfile.cabal
@@ -1,10 +1,10 @@
 name:          sendfile
-version:       0.3.1
-stability:     experimental
+version:       0.4
+stability:     provisional
 synopsis:      A portable sendfile library
 description:   A library which exposes zero-copy sendfile functionality in a portable way. If a platform does not support sendfile, a fallback implementation in haskell is provided.
                .
-               Currently supported platforms: Windows 2000+ (Native), Linux 2.6+ (Native), Everything else (Haskell).
+               Currently supported platforms: Windows 2000+ (Native), Linux 2.6+ (Native), FreeBSD (Untested!), Everything else (Haskell).
 
 license:       BSD3
 license-file:  LICENSE
@@ -33,19 +33,21 @@
 
     if os(windows) && !flag(portable)
       cpp-options: -DWIN32_SENDFILE
-      build-depends: Win32
-      c-sources: csrc/sendfile_win32.c
+      build-depends: Win32 >= 2.2.0.0 && < 2.3
       extra-libraries: mswsock
       other-modules: Network.Socket.SendFile.Win32
     else
       if os(linux) && !flag(portable)
         cpp-options: -DLINUX_SENDFILE
-        c-sources: csrc/sendfile_linux.c
         other-modules: Network.Socket.SendFile.Linux
       else
-        cpp-options: -DPORTABLE_SENDFILE
-        other-modules: Network.Socket.SendFile.Portable
-        build-depends: bytestring >= 0.9.1.4 && < 0.10
+        if os(freebsd) && !flag(portable)
+          cpp-options: -DFREEBSD_SENDFILE
+          other-modules: Network.Socket.SendFile.FreeBSD
+        else
+          cpp-options: -DPORTABLE_SENDFILE
+          build-depends: bytestring >= 0.9.1.4 && < 0.10,
+                         network-bytestring >= 0.1.1.3 && < 0.2
 
 source-repository head
     type:     darcs
diff --git a/src/Network/Socket/SendFile.hs b/src/Network/Socket/SendFile.hs
--- a/src/Network/Socket/SendFile.hs
+++ b/src/Network/Socket/SendFile.hs
@@ -1,28 +1,59 @@
--- | A cross-platform wrapper for sendfile -- this implements an available operating-system call if supported, otherwise it falls back to a portable haskell implementation. SendFile will flush the output Handle before transmission.
+-- | A cross-platform wrapper for sendfile -- this implements an available operating-system call if supported, otherwise it falls back to a portable haskell implementation.
 --
---   Keep in mind that the input should only be a `Handle` derived from a network socket (by using socketToHandle). Using something other than a network socket for the input Handle will result in undefined behavior. Furthermore, for consistent read/write behavior, both the output and input handles should be opened in Binary mode rather than Text mode (especially if you are using hSeek).
+--   Two interfaces are provided for both the unsafe and safe sets of functions. The first interface accepts an output socket\/handle and the path of the file you want to send; sendFile and unsafeSendFile comprise this interface. The second interface accepts an output socket\/handle, a handle to the file you want to send, and the number of bytes you want to send; sendFile' and unsafeSendFile' comprise this interface.
+--
+--   For consistent read/write behavior with either sendFile' or unsafeSendFile', the input handle should be opened in Binary mode rather than Text mode (especially if you are using hSeek before sending).
+--
+
 module Network.Socket.SendFile (
+    -- * Safe functions (recommended)
     sendFile,
     sendFile',
+    -- * Unsafe functions (not recommended)
+    -- | With unsafeSendFile and unsafeSendFile' the output should only be a `Handle` derived from a network socket (by using socketToHandle). These functions are unsafe because you cannot know whether or not a Handle is actually a `Socket` at compile-time. If you try to use  a `Handle` for the output which is not in fact a socket, you will get a runtime error.
+    --
+    --   These functions are provided for convenience given that the current high-level interface in the Network package gives you a `Handle` when you use accept. They may be deprecated in the future.
+    
+    unsafeSendFile,
+    unsafeSendFile',
+    -- * Utility functions
     sendFileMode
     ) where
+import qualified Network.Socket.SendFile.Internal (sendFile, sendFile', sendFileMode, unsafeSendFile, unsafeSendFile')
     
-import qualified Network.Socket.SendFile.Internal (sendFile, sendFile', sendFileMode)
 import System.IO (Handle)
+import Network.Socket (Socket)
 
--- | The simplest interface. Simply give it an output `Handle` and the `FilePath` to the input file.
-sendFile :: Handle   -- ^ The output handle
-         -> FilePath -- ^ The path where the input file resides
-         -> IO ()
+-- | The simplest interface. Simply give it an output `Socket` and the `FilePath` to the input file.
+sendFile
+    :: Socket   -- ^ The output socket
+    -> FilePath -- ^ The path where the input file resides
+    -> IO ()
 sendFile = Network.Socket.SendFile.Internal.sendFile
 
--- | A more powerful interface than sendFile, sendFile' accepts a `Handle` for the input file instead of a `FilePath` and the number of bytes you would like to read; this number must be a positive integer. This unlocks the full potential `Handle`(s). For instance, if you wanted to start reading from a particular offset, you could utilize `hSeek`. If you need the file size you can use 'hFileSize'.
-sendFile' :: Handle  -- ^ The output handle
-          -> Handle  -- ^ The input handle
-          -> Integer -- ^ The number of bytes to read
-          -> IO ()
+-- | A more powerful interface than sendFile, sendFile' accepts a `Handle` for the input file instead of a `FilePath` and the number of bytes you would like to read; this number must be a positive integer. This unlocks the full potential `Handle`(s). For instance, if you wanted to start reading from a particular offset in the file you could utilize `hSeek`; if you needed the file size you could use 'hFileSize'.
+sendFile'
+    :: Socket  -- ^ The output socket
+    -> Handle  -- ^ The input file handle
+    -> Integer -- ^ The number of bytes to send
+    -> IO ()   -- 
 sendFile' = Network.Socket.SendFile.Internal.sendFile'
 
--- | Returns the mode that sendfile was compiled with. Mainly for debugging use. Possible values are 'WIN32_SENDFILE', 'LINUX_SENDFILE', and 'PORTABLE_SENDFILE'.
+-- | The unsafe version of sendFile which accepts a `Handle` instead of a `Socket` for the output.  It will flush the output handle before sending any file data.
+unsafeSendFile
+    :: Handle   -- ^ The output handle
+    -> FilePath -- ^ The path where the input file resides
+    -> IO ()
+unsafeSendFile = Network.Socket.SendFile.Internal.unsafeSendFile
+
+-- | The unsafe version of sendFile' which accepts a `Handle` instead of a `Socket` for the output. It will flush the output handle before sending any file data.
+unsafeSendFile'
+    :: Handle  -- ^ The output handle
+    -> Handle  -- ^ The input file handle
+    -> Integer -- ^ The number of bytes to send
+    -> IO ()
+unsafeSendFile' = Network.Socket.SendFile.Internal.unsafeSendFile'
+
+-- | Returns the mode that sendfile was compiled with. Mainly for debugging use. Possible values are 'WIN32_SENDFILE', 'LINUX_SENDFILE', 'FREEBSD_SENDFILE', and 'PORTABLE_SENDFILE'.
 sendFileMode :: String -- ^ The mode that sendfile was compiled with
 sendFileMode = Network.Socket.SendFile.Internal.sendFileMode
diff --git a/src/Network/Socket/SendFile/FreeBSD.hs b/src/Network/Socket/SendFile/FreeBSD.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Socket/SendFile/FreeBSD.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+-- | FreeBSD system-dependent code for 'sendfile'.
+module Network.Socket.SendFile.FreeBSD (_sendFile) where
+import Foreign.C.Error (throwErrnoIfMinus1_)
+import Foreign.C.Types (CInt, CSize)
+import Foreign.Ptr (Ptr, nullPtr)
+import System.Posix.Types (COff, Fd)
+
+_sendFile :: Fd -> Fd -> Integer -> IO ()
+_sendFile out_fd in_fd count =
+    throwErrnoIfMinus1_
+      "Network.Socket.SendFile.FreeBSD.sendFile'"
+      (c_sendfile_freebsd in_fd out_fd 0 (fromIntegral count) nullPtr nullPtr 0)
+
+foreign import ccall unsafe "sys/uio.h sendfile" c_sendfile_freebsd
+    :: Fd -> Fd -> COff -> CSize -> Ptr () -> Ptr COff -> CInt -> IO CInt
+
diff --git a/src/Network/Socket/SendFile/Internal.hs b/src/Network/Socket/SendFile/Internal.hs
--- a/src/Network/Socket/SendFile/Internal.hs
+++ b/src/Network/Socket/SendFile/Internal.hs
@@ -1,16 +1,24 @@
 {-# LANGUAGE CPP #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
 module Network.Socket.SendFile.Internal (
     sendFile,
     sendFile',
-    sendFileMode
+    sendFileMode,
+    unsafeSendFile,
+    unsafeSendFile',
     ) where
 
+import Network.Socket (Socket(..), fdSocket)
 import System.IO (
     Handle,
     IOMode(..),
     hFileSize,
+    hFlush,
     withBinaryFile
     )
+import System.Posix.Types (Fd(..))
+import GHC.Handle (withHandle_)
+import GHC.IOBase (haFD)
 
 #if defined(WIN32_SENDFILE)
 import Network.Socket.SendFile.Win32 (_sendFile)
@@ -26,20 +34,60 @@
 sendFileMode = "LINUX_SENDFILE"
 #endif
 
+#if defined(FREEBSD_SENDFILE)
+import Network.Socket.SendFile.FreeBSD (_sendFile)
+
+sendFileMode :: String
+sendFileMode = "FREEBSD_SENDFILE"
+#endif
+
 #if defined(PORTABLE_SENDFILE)
-import Network.Socket.SendFile.Portable (_sendFile)
+import Data.ByteString.Char8 (hGet, hPutStr)
+import Network.Socket.ByteString (sendAll)
 
 sendFileMode :: String
 sendFileMode = "PORTABLE_SENDFILE"
+
+sendFile' :: Socket -> Handle -> Integer -> IO ()
+sendFile' = wrapSendFile' $ \outs inp count -> do
+    sendAll outs =<< hGet inp (fromIntegral count)
+    return ()
+
+unsafeSendFile' :: Handle -> Handle -> Integer -> IO ()
+unsafeSendFile' = wrapSendFile' $ \outp inp count -> do
+    hPutStr outp =<< hGet inp (fromIntegral count)
+    hFlush outp -- match the behavior that all data is "flushed to the os" of native implementations
+#else
+sendFile' :: Socket -> Handle -> Integer -> IO ()
+sendFile' outs inp 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 count
+
+unsafeSendFile' :: Handle -> Handle -> Integer -> IO ()
+unsafeSendFile' outp inp count = do
+    hFlush outp -- flush outp before sending
+    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 count
 #endif
 
-sendFile :: Handle -> FilePath -> IO ()
-sendFile outp infp = withBinaryFile infp ReadMode $ \inp -> do
+-- | wraps sendFile' to check arguments
+wrapSendFile' :: (a -> b -> Integer -> IO ()) -> a -> b -> Integer -> IO ()
+wrapSendFile' fun outp inp count
+    | count < 0  = error "SendFile - count must be a positive integer"
+    | count == 0 = return () -- Send nothing -- why do the work? Also, Windows treats '0' as 'send the whole file'.
+    | otherwise  = fun outp inp count
+
+sendFile :: Socket -> FilePath -> IO ()
+sendFile outs infp = withBinaryFile infp ReadMode $ \inp -> do
     count <- hFileSize inp
-    sendFile' outp inp count
+    sendFile' outs inp count
 
-sendFile' :: Handle -> Handle -> Integer -> IO ()
-sendFile' outp inp count
-    | count < 0  = error "sendFile' - count must be a positive integer"
-    | count == 0 = return () -- Send nothing -- why do the work? Also, Windows treats '0' as 'send the whole file'.
-    | otherwise  = _sendFile outp inp count
+unsafeSendFile :: Handle -> FilePath -> IO ()
+unsafeSendFile outp infp = withBinaryFile infp ReadMode $ \inp -> do
+    count <- hFileSize inp
+    unsafeSendFile' outp inp count
diff --git a/src/Network/Socket/SendFile/Linux.hs b/src/Network/Socket/SendFile/Linux.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Socket/SendFile/Linux.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+-- | Linux system-dependent code for 'sendfile'.
+module Network.Socket.SendFile.Linux (_sendFile) where
+import Foreign.C.Error (throwErrnoIfMinus1_)
+import Foreign.C.Types (CSize)
+import Foreign.Ptr (Ptr, nullPtr)
+import System.Posix.Types (COff, Fd)
+
+_sendFile :: Fd -> Fd -> Integer -> IO ()
+_sendFile out_fd in_fd count =
+    throwErrnoIfMinus1_
+      "Network.Socket.SendFile.Linux.sendFile'"
+      (c_sendfile_linux out_fd in_fd nullPtr (fromIntegral count))
+
+foreign import ccall unsafe "sys/sendfile.h sendfile" c_sendfile_linux
+    :: Fd -> Fd -> Ptr COff -> CSize -> IO CSize
+
diff --git a/src/Network/Socket/SendFile/Linux.hsc b/src/Network/Socket/SendFile/Linux.hsc
deleted file mode 100644
--- a/src/Network/Socket/SendFile/Linux.hsc
+++ /dev/null
@@ -1,27 +0,0 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
--- | Linux system-dependent code for 'sendfile'.
-module Network.Socket.SendFile.Linux (_sendFile) where
-import Data.Int
-import Data.Word
-import Foreign.C.Error (throwErrno)
-import GHC.IOBase (FD, haFD)
-import GHC.Handle (withHandle_)
-import System.IO (Handle, hFlush)
-
-#include <sys/sendfile.h>
-
-_sendFile :: Handle -> Handle -> Integer -> IO ()
-_sendFile outp inp count = do
-    -- flush outp before sending
-    hFlush outp
-    withHandle_ "Network.Socket.SendFile.Linux.sendFile'" outp $ \outp' -> do
-    withHandle_ "Network.Socket.SendFile.Linux.sendFile'" inp $ \inp' -> do 
-    let out_fd = haFD outp'
-    let in_fd = haFD inp'
-    res <- c_sendfile_linux out_fd in_fd (fromIntegral count)
-    if res == -1
-        then throwErrno "Network.Socket.SendFile.Linux.sendFile'"
-        else return ()
-
-foreign import ccall unsafe
-    c_sendfile_linux :: FD -> FD -> (#type size_t) -> IO (#type ssize_t)
diff --git a/src/Network/Socket/SendFile/Portable.hs b/src/Network/Socket/SendFile/Portable.hs
deleted file mode 100644
--- a/src/Network/Socket/SendFile/Portable.hs
+++ /dev/null
@@ -1,13 +0,0 @@
--- | Portable implementation of sendfile.
-module Network.Socket.SendFile.Portable (_sendFile) where
-
-import Data.ByteString.Char8
-import Prelude hiding (readFile)
-import System.IO (Handle, hFlush)
-
-
--- FIXME: possibly immature / inefficient implementation
-_sendFile :: Handle -> Handle -> Integer -> IO ()
-_sendFile outp inp count = do
-    hPutStr outp =<< hGet inp (fromIntegral count)
-    hFlush outp -- match the behavior that all data is "flushed to the os" of native implementations
diff --git a/src/Network/Socket/SendFile/Win32.hsc b/src/Network/Socket/SendFile/Win32.hsc
--- a/src/Network/Socket/SendFile/Win32.hsc
+++ b/src/Network/Socket/SendFile/Win32.hsc
@@ -1,43 +1,54 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
--- | Win32 system-dependent code for 'TransmitFile'.
-module Network.Socket.SendFile.Win32 (_sendFile) where
-import Data.Int
-import Data.Word
-import Foreign.C.Error (throwErrno)
-import Foreign.Ptr (IntPtr, intPtrToPtr)
-import GHC.Handle (withHandle_)
-import GHC.IOBase (FD, haFD)
-import System.IO (Handle, hFlush)
-import System.Win32.Types
-
-#include <windows.h>
-
-_sendFile :: Handle -> Handle -> Integer -> IO ()
-_sendFile outp inp count = do
-    hFlush outp -- flush the buffer before invoking transmitFile
-    withHandle_ "Network.Socket.SendFile.Win32.sendFile'" outp $ \outp' -> do
-    withHandle_ "Network.Socket.SendFile.Win32.sendFile'" inp $ \inp' -> do
-    let out_fd = haFD outp'
-    in_hdl <- get_osfhandle (haFD inp')
-    transmitFile (fromIntegral out_fd) in_hdl (fromIntegral count)
-
-get_osfhandle :: FD        -- ^ User file descriptor.
-              -> IO HANDLE -- ^ The operating-system file handle.
-get_osfhandle fd = do
-    res <- c_get_osfhandle fd
-    if res == (#const INVALID_HANDLE_VALUE)
-      then throwErrno "Network.Socket.SendFile.Win32.get_osfhandle"
-      else return (intPtrToPtr res)
-
-transmitFile :: FD     -- ^ A handle to a connected socket.
-             -> HANDLE -- ^ A handle to the open file that the TransmitFile function transmits.
-             -> DWORD  -- ^ The number of bytes in the file to transmit.
-             -> IO ()
-transmitFile out_fd in_hdl count =
-    failIf_ (== 0) "Network.Socket.SendFile.Win32.transmitFile" (c_TransmitFile out_fd in_hdl count)
-    
-foreign import ccall unsafe
-    c_get_osfhandle :: FD -> IO IntPtr
-    
-foreign import ccall unsafe
-    c_TransmitFile :: FD -> HANDLE -> DWORD -> IO (#type BOOL)
+{-# LANGUAGE ForeignFunctionInterface #-}
+-- | Win32 system-dependent code for 'TransmitFile'.
+module Network.Socket.SendFile.Win32 (_sendFile) where
+import Foreign.C.Error (throwErrnoIf)
+import Foreign.Ptr (IntPtr, Ptr, intPtrToPtr, nullPtr)
+import Foreign.C.Types (CInt)
+import System.Posix.Types (Fd)
+import System.Win32.Types (DWORD, HANDLE, failIfZero)
+
+#include <windows.h>
+#include <mswsock.h>
+
+type SOCKET = Fd
+
+_sendFile :: Fd -> Fd -> Integer -> IO ()
+_sendFile out_fd in_fd count = do
+    in_hdl <- get_osfhandle in_fd
+    transmitFile out_fd in_hdl (fromIntegral count)
+
+get_osfhandle :: Fd        -- ^ User file descriptor.
+              -> IO HANDLE -- ^ The operating-system file handle.
+get_osfhandle fd = do
+    res <- throwErrnoIf
+             (== (#const INVALID_HANDLE_VALUE))
+             "Network.Socket.SendFile.Win32.get_osfhandle"
+             (c_get_osfhandle fd)
+    return (intPtrToPtr res)
+
+transmitFile :: SOCKET -- ^ A handle to a connected socket.
+             -> HANDLE -- ^ A handle to the open file that the TransmitFile function transmits.
+             -> DWORD  -- ^ The number of bytes in the file to transmit.
+             -> IO ()
+transmitFile out_fd in_hdl count = do
+    failIfZero
+      "Network.Socket.SendFile.Win32.transmitFile"
+      (c_TransmitFile out_fd in_hdl count 0 nullPtr nullPtr (#const TF_USE_KERNEL_APC))
+    return ()
+
+-- http://support.microsoft.com/kb/99173 - MAY BE IMPORTANT
+-- http://msdn.microsoft.com/en-us/library/ks2530z6.aspx
+foreign import ccall unsafe "io.h _get_osfhandle"
+    c_get_osfhandle :: Fd
+                    -> IO IntPtr
+
+-- http://msdn.microsoft.com/en-us/library/ms740565(VS.85).aspx
+foreign import stdcall unsafe "mswsock.h TransmitFile"
+    c_TransmitFile :: SOCKET
+                   -> HANDLE
+                   -> DWORD
+                   -> DWORD
+                   -> Ptr ()
+                   -> Ptr ()
+                   -> DWORD
+                   -> IO CInt
