{-# LINE 1 "Network/Socket/ByteString/IO.hsc" #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE OverloadedStrings #-}
module Network.Socket.ByteString.IO
(
send
, sendAll
, sendTo
, sendAllTo
, sendMany
, sendManyTo
, recv
, recvFrom
, waitWhen0
) where
import Control.Concurrent (threadWaitWrite, rtsSupportsBoundThreads)
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import Data.ByteString.Internal (createAndTrim)
import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
import Foreign.Marshal.Alloc (allocaBytes)
import Foreign.Ptr (castPtr)
import Network.Socket.Buffer
import Network.Socket.ByteString.Internal
import Network.Socket.Imports
import Network.Socket.Types
{-# LINE 59 "Network/Socket/ByteString/IO.hsc" #-}
import Control.Monad (zipWithM_)
import Foreign.Marshal.Array (allocaArray)
import Foreign.Marshal.Utils (with)
import Foreign.Ptr (Ptr, plusPtr)
import Foreign.Storable (Storable(..))
import Network.Socket.Internal
import Network.Socket.ByteString.IOVec (IOVec(..))
import Network.Socket.ByteString.MsgHdr (MsgHdr(..))
{-# LINE 69 "Network/Socket/ByteString/IO.hsc" #-}
send :: Socket
-> ByteString
-> IO Int
send :: Socket -> ByteString -> IO Int
send Socket
s ByteString
xs = ByteString -> (CStringLen -> IO Int) -> IO Int
forall a. ByteString -> (CStringLen -> IO a) -> IO a
unsafeUseAsCStringLen ByteString
xs ((CStringLen -> IO Int) -> IO Int)
-> (CStringLen -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$ \(Ptr CChar
str, Int
len) ->
Socket -> Ptr Word8 -> Int -> IO Int
sendBuf Socket
s (Ptr CChar -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr CChar
str) Int
len
waitWhen0 :: Int -> Socket -> IO ()
waitWhen0 :: Int -> Socket -> IO ()
waitWhen0 Int
0 Socket
s = Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
rtsSupportsBoundThreads (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
Socket -> (CInt -> IO ()) -> IO ()
forall r. Socket -> (CInt -> IO r) -> IO r
withFdSocket Socket
s ((CInt -> IO ()) -> IO ()) -> (CInt -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \CInt
fd -> Fd -> IO ()
threadWaitWrite (Fd -> IO ()) -> Fd -> IO ()
forall a b. (a -> b) -> a -> b
$ CInt -> Fd
forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
fd
waitWhen0 Int
_ Socket
_ = () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
sendAll :: Socket
-> ByteString
-> IO ()
sendAll :: Socket -> ByteString -> IO ()
sendAll Socket
_ ByteString
"" = () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
sendAll Socket
s ByteString
bs = do
Int
sent <- Socket -> ByteString -> IO Int
send Socket
s ByteString
bs
Int -> Socket -> IO ()
waitWhen0 Int
sent Socket
s
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
sent Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Socket -> ByteString -> IO ()
sendAll Socket
s (ByteString -> IO ()) -> ByteString -> IO ()
forall a b. (a -> b) -> a -> b
$ Int -> ByteString -> ByteString
B.drop Int
sent ByteString
bs
sendTo :: SocketAddress sa =>
Socket
-> ByteString
-> sa
-> IO Int
sendTo :: Socket -> ByteString -> sa -> IO Int
sendTo Socket
s ByteString
xs sa
sa =
ByteString -> (CStringLen -> IO Int) -> IO Int
forall a. ByteString -> (CStringLen -> IO a) -> IO a
unsafeUseAsCStringLen ByteString
xs ((CStringLen -> IO Int) -> IO Int)
-> (CStringLen -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$ \(Ptr CChar
str, Int
len) -> Socket -> Ptr CChar -> Int -> sa -> IO Int
forall sa a.
SocketAddress sa =>
Socket -> Ptr a -> Int -> sa -> IO Int
sendBufTo Socket
s Ptr CChar
str Int
len sa
sa
sendAllTo :: SocketAddress sa =>
Socket
-> ByteString
-> sa
-> IO ()
sendAllTo :: Socket -> ByteString -> sa -> IO ()
sendAllTo Socket
_ ByteString
"" sa
_ = () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
sendAllTo Socket
s ByteString
xs sa
sa = do
Int
sent <- Socket -> ByteString -> sa -> IO Int
forall sa. SocketAddress sa => Socket -> ByteString -> sa -> IO Int
sendTo Socket
s ByteString
xs sa
sa
Int -> Socket -> IO ()
waitWhen0 Int
sent Socket
s
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
sent Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Socket -> ByteString -> sa -> IO ()
forall sa. SocketAddress sa => Socket -> ByteString -> sa -> IO ()
sendAllTo Socket
s (Int -> ByteString -> ByteString
B.drop Int
sent ByteString
xs) sa
sa
sendMany :: Socket
-> [ByteString]
-> IO ()
sendMany :: Socket -> [ByteString] -> IO ()
{-# LINE 140 "Network/Socket/ByteString/IO.hsc" #-}
sendMany _ [] = return ()
sendMany s cs = do
sent <- sendManyInner
waitWhen0 sent s
when (sent >= 0) $ sendMany s $ remainingChunks sent cs
where
sendManyInner =
fmap fromIntegral . withIOVec cs $ \(iovsPtr, iovsLen) ->
withFdSocket s $ \fd -> do
let len = fromIntegral $ min iovsLen (1024)
{-# LINE 150 "Network/Socket/ByteString/IO.hsc" #-}
throwSocketErrorWaitWrite s "Network.Socket.ByteString.sendMany" $
c_writev fd iovsPtr len
{-# LINE 155 "Network/Socket/ByteString/IO.hsc" #-}
sendManyTo :: Socket
-> [ByteString]
-> SockAddr
-> IO ()
{-# LINE 167 "Network/Socket/ByteString/IO.hsc" #-}
sendManyTo _ [] _ = return ()
sendManyTo s cs addr = do
sent <- fromIntegral <$> sendManyToInner
waitWhen0 sent s
when (sent >= 0) $ sendManyTo s (remainingChunks sent cs) addr
where
sendManyToInner =
withSockAddr addr $ \addrPtr addrSize ->
withIOVec cs $ \(iovsPtr, iovsLen) -> do
let msgHdr = MsgHdr
addrPtr (fromIntegral addrSize)
iovsPtr (fromIntegral iovsLen)
withFdSocket s $ \fd ->
with msgHdr $ \msgHdrPtr ->
throwSocketErrorWaitWrite s "Network.Socket.ByteString.sendManyTo" $
c_sendmsg fd msgHdrPtr 0
{-# LINE 186 "Network/Socket/ByteString/IO.hsc" #-}
recv :: Socket
-> Int
-> IO ByteString
recv :: Socket -> Int -> IO ByteString
recv Socket
s Int
nbytes
| Int
nbytes Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = IOError -> IO ByteString
forall a. IOError -> IO a
ioError (String -> IOError
mkInvalidRecvArgError String
"Network.Socket.ByteString.recv")
| Bool
otherwise = Int -> (Ptr Word8 -> IO Int) -> IO ByteString
createAndTrim Int
nbytes ((Ptr Word8 -> IO Int) -> IO ByteString)
-> (Ptr Word8 -> IO Int) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
ptr -> Socket -> Ptr Word8 -> Int -> IO Int
recvBuf Socket
s Ptr Word8
ptr Int
nbytes
recvFrom :: SocketAddress sa =>
Socket
-> Int
-> IO (ByteString, sa)
recvFrom :: Socket -> Int -> IO (ByteString, sa)
recvFrom Socket
sock Int
nbytes =
Int -> (Ptr CChar -> IO (ByteString, sa)) -> IO (ByteString, sa)
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes Int
nbytes ((Ptr CChar -> IO (ByteString, sa)) -> IO (ByteString, sa))
-> (Ptr CChar -> IO (ByteString, sa)) -> IO (ByteString, sa)
forall a b. (a -> b) -> a -> b
$ \Ptr CChar
ptr -> do
(Int
len, sa
sockaddr) <- Socket -> Ptr CChar -> Int -> IO (Int, sa)
forall sa a.
SocketAddress sa =>
Socket -> Ptr a -> Int -> IO (Int, sa)
recvBufFrom Socket
sock Ptr CChar
ptr Int
nbytes
ByteString
str <- CStringLen -> IO ByteString
B.packCStringLen (Ptr CChar
ptr, Int
len)
(ByteString, sa) -> IO (ByteString, sa)
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString
str, sa
sockaddr)
{-# LINE 228 "Network/Socket/ByteString/IO.hsc" #-}
remainingChunks :: Int -> [ByteString] -> [ByteString]
remainingChunks :: Int -> [ByteString] -> [ByteString]
remainingChunks Int
_ [] = []
remainingChunks Int
i (ByteString
x:[ByteString]
xs)
| Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
len = Int -> ByteString -> ByteString
B.drop Int
i ByteString
x ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString]
xs
| Bool
otherwise = let i' :: Int
i' = Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
len in Int
i' Int -> [ByteString] -> [ByteString]
`seq` Int -> [ByteString] -> [ByteString]
remainingChunks Int
i' [ByteString]
xs
where
len :: Int
len = ByteString -> Int
B.length ByteString
x
withIOVec :: [ByteString] -> ((Ptr IOVec, Int) -> IO a) -> IO a
withIOVec :: [ByteString] -> ((Ptr IOVec, Int) -> IO a) -> IO a
withIOVec [ByteString]
cs (Ptr IOVec, Int) -> IO a
f =
Int -> (Ptr IOVec -> IO a) -> IO a
forall a b. Storable a => Int -> (Ptr a -> IO b) -> IO b
allocaArray Int
csLen ((Ptr IOVec -> IO a) -> IO a) -> (Ptr IOVec -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Ptr IOVec
aPtr -> do
(Ptr IOVec -> ByteString -> IO ())
-> [Ptr IOVec] -> [ByteString] -> IO ()
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m ()
zipWithM_ Ptr IOVec -> ByteString -> IO ()
pokeIov (Ptr IOVec -> [Ptr IOVec]
forall a. Ptr a -> [Ptr a]
ptrs Ptr IOVec
aPtr) [ByteString]
cs
(Ptr IOVec, Int) -> IO a
f (Ptr IOVec
aPtr, Int
csLen)
where
csLen :: Int
csLen = [ByteString] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ByteString]
cs
ptrs :: Ptr a -> [Ptr a]
ptrs = (Ptr a -> Ptr a) -> Ptr a -> [Ptr a]
forall a. (a -> a) -> a -> [a]
iterate (Ptr a -> Int -> Ptr a
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` IOVec -> Int
forall a. Storable a => a -> Int
sizeOf (IOVec
forall a. HasCallStack => a
undefined :: IOVec))
pokeIov :: Ptr IOVec -> ByteString -> IO ()
pokeIov Ptr IOVec
ptr ByteString
s =
ByteString -> (CStringLen -> IO ()) -> IO ()
forall a. ByteString -> (CStringLen -> IO a) -> IO a
unsafeUseAsCStringLen ByteString
s ((CStringLen -> IO ()) -> IO ()) -> (CStringLen -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \(Ptr CChar
sPtr, Int
sLen) ->
Ptr IOVec -> IOVec -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr IOVec
ptr (IOVec -> IO ()) -> IOVec -> IO ()
forall a b. (a -> b) -> a -> b
$ Ptr CChar -> CSize -> IOVec
IOVec Ptr CChar
sPtr (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
sLen)
{-# LINE 255 "Network/Socket/ByteString/IO.hsc" #-}