diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,31 @@
+Copyright Johan Tibell 2007
+
+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 Johan Tibell 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.
+
diff --git a/Network/Socket/ByteString.cpphs b/Network/Socket/ByteString.cpphs
new file mode 100644
--- /dev/null
+++ b/Network/Socket/ByteString.cpphs
@@ -0,0 +1,210 @@
+{-# OPTIONS_GHC -cpp #-}
+
+-- |
+-- Module      : Network.Socket.ByteString
+-- Copyright   : (c) Johan Tibell 2007
+-- License     : BSD-style
+--
+-- Maintainer  : johan.tibell@gmail.com
+-- Stability   : experimental
+-- Portability : portable
+--
+-- | A module for efficiently transmitting data over sockets. For
+-- detailed documentation consult your favorite POSIX socket
+-- reference. All functions communicate failures by converting the
+-- error number to an 'System.IO.IOError'.
+--
+-- This module is intended to be imported together with 'Network.Socket' like so:
+--
+-- > import Network.Socket hiding (send, sendTo, recv, recvFrom)
+-- > import Network.Socket.ByteString
+--
+module Network.Socket.ByteString
+    (
+     -- * Send a message on a socket
+     -- | Functions used to transmit a message to another socket.
+     send,
+     sendTo,
+
+     -- * Receive a message from a socket
+     -- | Functions used to receive messages from a socket, and may be
+     -- used to receive data on a socket whether or not it is
+     -- connection-oriented.
+     recv,
+     recvFrom
+    ) where
+
+import Control.Monad (liftM)
+import Data.ByteString (ByteString)
+import qualified Data.ByteString as B
+import Data.ByteString.Internal (create)
+import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
+import Foreign.C.Error
+import Foreign.C.Types (CChar, CInt, CSize)
+import Foreign.Marshal.Alloc (allocaBytes)
+import Foreign.Ptr (Ptr, castPtr)
+import Network.Socket (SockAddr, Socket(..), sendBufTo, recvBufFrom)
+
+#if defined(__GLASGOW_HASKELL__)
+import GHC.Conc (threadWaitRead, threadWaitWrite)
+import GHC.IOBase (IOErrorType(..), IOException(..))
+# if defined(mingw32_HOST_OS)
+import GHC.Handle (readRawBufferPtr, writeRawBufferPtr)
+# endif
+#else
+import System.IO.Unsafe (unsafePerformIO)
+#endif
+
+#ifndef CALLCONV
+# ifdef WITH_WINSOCK
+#  define CALLCONV stdcall
+# else
+#  define CALLCONV ccall
+# endif
+#endif
+foreign import CALLCONV unsafe "send"
+  c_send :: CInt -> Ptr a -> CSize -> CInt -> IO CInt
+foreign import CALLCONV unsafe "recv"
+  c_recv :: CInt -> Ptr CChar -> CSize -> CInt -> IO CInt
+
+-- -----------------------------------------------------------------------------
+-- Sending
+
+-- | Transmit a message to another socket. The socket must be in a
+-- connected state so that the intended recipient is known.
+send :: Socket      -- ^ Bound\/Connected socket.
+     -> ByteString  -- ^ Data to send.
+     -> IO Int      -- ^ Number of bytes sent.
+send (MkSocket s _family _stype _protocol status) xs = do
+  unsafeUseAsCStringLen xs $ \(str, len) -> do
+    liftM fromIntegral $
+#if defined(__GLASGOW_HASKELL__) && defined(mingw32_HOST_OS)
+      writeRawBufferPtr "Network.Socket.ByteString.send" (fromIntegral s) True str 0
+                (fromIntegral len)
+#else
+# if !defined(__HUGS__)
+     throwErrnoIfMinus1Retry_repeatOnBlock "send"
+        (threadWaitWrite (fromIntegral s)) $
+# endif
+        c_send s str (fromIntegral len) 0{-flags-}
+#endif
+
+-- | Transmit a message to another socket. The recipient can be
+-- specified explicitly so the socket must not (but can be) in a
+-- connected state.
+sendTo :: Socket      -- ^ (Possibly) bound\/connected socket.
+       -> ByteString  -- ^ Data to send.
+       -> SockAddr    -- ^ Recipient address.
+       -> IO Int      -- ^ Number of bytes sent.
+sendTo sock xs addr = unsafeUseAsCStringLen xs $
+                      \(str, len) -> sendBufTo sock str len addr
+
+-- -----------------------------------------------------------------------------
+-- Receiving
+
+-- | Receive a message from another socket. The socket must be in a
+-- connected state so that the intended recipient is known. Note that
+-- the length of the received data can be smaller than specified
+-- maximum length. If the message is longer than the specified length
+-- it may be discarded depending on the type of socket. May block
+-- until a message arrives.
+recv :: Socket          -- ^ Bound\/connected socket.
+     -> Int             -- Maximum number of bytes to receive.
+     -> IO ByteString   -- Data received.
+recv sock@(MkSocket s _ _ _ _) nbytes
+    | nbytes <= 0 = ioError (mkInvalidRecvArgError "Network.Socket.ByteString.recv")
+    | otherwise   = do
+      create nbytes $ \ptr -> do
+        len <-
+#if defined(__GLASGOW_HASKELL__) && defined(mingw32_HOST_OS)
+            readRawBufferPtr "Network.Socket.ByteString.recvLen" (fromIntegral s) True
+                             (castPtr ptr) 0 (fromIntegral nbytes)
+#else
+# if !defined(__HUGS__)
+             throwErrnoIfMinus1Retry_repeatOnBlock "recv"
+                    (threadWaitRead (fromIntegral s)) $
+# endif
+                            c_recv s (castPtr ptr) (fromIntegral nbytes) 0{-flags-}
+#endif
+        if fromIntegral len == 0
+            then ioError (mkEOFError "Network.Socket.ByteString.recv")
+            else return ()
+
+-- | Similar to 'recv' but can be used to receive data on a socket
+-- that is not connection-oriented.
+recvFrom :: Socket                     -- ^ (Possibly) bound\/connected socket.
+         -> Int                        -- ^ Maximum number of bytes to receive.
+         -> IO (ByteString, SockAddr)  -- ^ Data received and sender address.
+recvFrom sock nbytes =
+    allocaBytes nbytes $ \ptr -> do
+      (len, sockaddr) <- recvBufFrom sock ptr nbytes
+      str <- B.packCStringLen (ptr, len)
+      return (str, sockaddr)
+
+mkInvalidRecvArgError :: String -> IOError
+mkInvalidRecvArgError loc = IOError Nothing
+#ifdef __GLASGOW_HASKELL__
+                                    InvalidArgument
+#else
+                                    IllegalOperation
+#endif
+                                    loc "non-positive length" Nothing
+
+mkEOFError :: String -> IOError
+mkEOFError loc = IOError Nothing EOF loc "end of file" Nothing
+
+-----------------------------------------------------------------------------
+-- Support for thread-safe blocking operations in GHC.
+
+#if defined(__GLASGOW_HASKELL__) && !(defined(HAVE_WINSOCK_H) && !defined(cygwin32_HOST_OS))
+{-# SPECIALISE
+    throwErrnoIfMinus1Retry_mayBlock
+         :: String -> IO CInt -> IO CInt -> IO CInt #-}
+throwErrnoIfMinus1Retry_mayBlock :: Num a => String -> IO a -> IO a -> IO a
+throwErrnoIfMinus1Retry_mayBlock name on_block act = do
+    res <- act
+    if res == -1
+        then do
+            err <- getErrno
+            if err == eINTR
+                then throwErrnoIfMinus1Retry_mayBlock name on_block act
+                else if err == eWOULDBLOCK || err == eAGAIN
+                        then on_block
+                        else throwErrno name
+        else return res
+
+throwErrnoIfMinus1Retry_repeatOnBlock :: Num a => String -> IO b -> IO a -> IO a
+throwErrnoIfMinus1Retry_repeatOnBlock name on_block act = do
+  throwErrnoIfMinus1Retry_mayBlock name (on_block >> repeat) act
+  where repeat = throwErrnoIfMinus1Retry_repeatOnBlock name on_block act
+
+#else
+throwErrnoIfMinus1Retry_mayBlock name _ act
+  = throwSocketErrorIfMinus1Retry name act
+
+throwErrnoIfMinus1Retry_repeatOnBlock name _ act
+  = throwSocketErrorIfMinus1Retry name act
+
+# if defined(HAVE_WINSOCK_H) && !defined(cygwin32_HOST_OS)
+throwSocketErrorIfMinus1Retry name act = do
+  r <- act
+  if (r == -1)
+   then do
+    rc   <- c_getLastError
+    case rc of
+      10093 -> do -- WSANOTINITIALISED
+        withSocketsDo (return ())
+        r <- act
+        if (r == -1)
+         then (c_getLastError >>= throwSocketError name)
+         else return r
+      _ -> throwSocketError name rc
+   else return r
+
+foreign import CALLCONV unsafe "WSAGetLastError"
+  c_getLastError :: IO CInt
+
+# else
+throwSocketErrorIfMinus1Retry name act = throwErrnoIfMinus1Retry name act
+# endif
+#endif /* __GLASGOW_HASKELL */
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,3 @@
+#!/usr/bin/env runhaskell
+> import Distribution.Simple
+> main = defaultMain
diff --git a/network-bytestring.cabal b/network-bytestring.cabal
new file mode 100644
--- /dev/null
+++ b/network-bytestring.cabal
@@ -0,0 +1,14 @@
+name:             network-bytestring
+version:          0.1
+synopsis:         Fast and memory efficient low-level networking
+description:      Faster and more memory efficient low-level socket functions using
+                  'Data.ByteString's instead of 'String's.
+license:          BSD3
+license-file:     LICENSE
+author:           Johan Tibell
+maintainer:       johan.tibell@gmail.com
+category:         Network
+build-depends:    base, bytestring, HUnit, network
+ghc-options:      -O
+exposed-modules:  Network.Socket.ByteString
+extensions:       CPP, ForeignFunctionInterface
