socket-0.6.0.0: src/System/Socket/Type/Stream.hsc
--------------------------------------------------------------------------------
-- |
-- Module : System.Socket
-- Copyright : (c) Lars Petersen 2015
-- License : MIT
--
-- Maintainer : info@lars-petersen.net
-- Stability : experimental
--------------------------------------------------------------------------------
module System.Socket.Type.Stream (
-- * Stream
Stream
-- * Convenience Operations
-- ** sendAll, receiveAll
, sendAll
, receiveAll
) where
import Control.Monad (when)
import Data.Int
import Data.Monoid
import qualified Data.ByteString as BS
import qualified Data.ByteString.Builder as BB
import qualified Data.ByteString.Builder.Extra as BB
import qualified Data.ByteString.Lazy as LBS
import System.Socket
#include "hs_socket.h"
data Stream
instance Type Stream where
typeNumber _ = (#const SOCK_STREAM)
-------------------------------------------------------------------------------
-- Convenience Operations
-------------------------------------------------------------------------------
-- | Like `send`, but operates on lazy `Data.ByteString.Lazy.ByteString`s and
-- continues until all data has been sent or an exception occured.
sendAll ::Socket f Stream p -> LBS.ByteString -> MessageFlags -> IO ()
sendAll s lbs flags =
LBS.foldlChunks
(\x bs-> x >> sendAll' bs
) (return ()) lbs
where
sendAll' bs = do
sent <- send s bs flags
when (sent < BS.length bs) $ sendAll' (BS.drop sent bs)
-- | Like `receive`, but operates on lazy `Data.ByteString.Lazy.ByteString`s and
-- continues until either an empty part has been received (peer closed
-- the connection) or given buffer limit has been exceeded or an
-- exception occured.
--
-- - The `Data.Int.Int64` parameter is a soft limit on how many bytes to receive.
-- Collection is stopped if the limit has been exceeded. The result might
-- be up to one internal buffer size longer than the given limit.
-- If the returned `Data.ByteString.Lazy.ByteString`s length is lower or
-- eqal than the limit, the data has not been truncated and the
-- transmission is complete.
receiveAll :: Socket f Stream p -> Int64 -> MessageFlags -> IO LBS.ByteString
receiveAll sock maxLen flags = collect 0 Data.Monoid.mempty
where
collect len accum
| len > maxLen = do
build accum
| otherwise = do
bs <- receive sock BB.smallChunkSize flags
if BS.null bs then do
build accum
else do
collect (len + fromIntegral (BS.length bs))
$! (accum `Data.Monoid.mappend` BB.byteString bs)
build accum = do
return (BB.toLazyByteString accum)