module System.Socket.Unsafe (
unsafeSend
, unsafeSendTo
, unsafeRecv
, unsafeRecvFrom
) where
import Data.Function
import Data.Monoid
import Control.Monad
import Control.Exception
import Control.Concurrent.MVar
import Foreign.C.Error
import Foreign.C.Types
import Foreign.Ptr
import System.Socket.Internal.Socket
import System.Socket.Internal.Event
import System.Socket.Internal.FFI
import System.Socket.Internal.Exception
import System.Socket.Internal.MsgFlags
import System.Socket.Address
import System.Socket.Type
import System.Socket.Protocol
unsafeSend :: (Address a, Type t, Protocol p) => Socket a t p -> Ptr b -> CSize -> MsgFlags -> IO CInt
unsafeSend (Socket mfd) bufPtr bufSize flags = do
fix $ \again-> do
ewb <- withMVar mfd $ \fd-> do
when (fd < 0) $ do
throwIO (SocketException eBADF)
fix $ \retry-> do
i <- c_send fd bufPtr bufSize (flags `mappend` msgNOSIGNAL)
if (i < 0) then do
e <- getErrno
if e == eWOULDBLOCK || e == eAGAIN
then threadWaitRead' fd >>= return . Left
else if e == eINTR
then retry
else throwIO (SocketException e)
else return (Right i)
case ewb of
Left wait -> wait >> again
Right bytesSent -> return bytesSent
unsafeSendTo :: (Address a, Type t, Protocol p) => Socket a t p -> Ptr b -> CSize -> MsgFlags -> Ptr a -> CInt -> IO CInt
unsafeSendTo (Socket mfd) bufPtr bufSize flags addrPtr addrSize = do
fix $ \again-> do
ewb <- withMVar mfd $ \fd-> do
when (fd < 0) $ do
throwIO (SocketException eBADF)
fix $ \retry-> do
i <- c_sendto fd bufPtr (fromIntegral bufSize) (flags `mappend` msgNOSIGNAL) addrPtr addrSize
if (i < 0) then do
e <- getErrno
if e == eWOULDBLOCK || e == eAGAIN
then threadWaitRead' fd >>= return . Left
else if e == eINTR
then retry
else throwIO (SocketException e)
else return (Right i)
case ewb of
Left wait -> wait >> again
Right bytesSent -> return (fromIntegral bytesSent)
unsafeRecv :: (Address a, Type t, Protocol p) => Socket a t p -> Ptr b -> CSize -> MsgFlags -> IO CInt
unsafeRecv (Socket mfd) bufPtr bufSize flags =
fix $ \again-> do
ewb <- withMVar mfd $ \fd-> do
when (fd < 0) $ do
throwIO (SocketException eBADF)
fix $ \retry-> do
i <- c_recv fd bufPtr bufSize flags
if (i < 0) then do
e <- getErrno
if e == eWOULDBLOCK || e == eAGAIN then do
threadWaitRead' fd >>= return . Left
else if e == eINTR
then retry
else throwIO (SocketException e)
else return (Right i)
case ewb of
Left wait -> wait >> again
Right bytesReceived -> return bytesReceived
unsafeRecvFrom :: (Address a, Type t, Protocol p) => Socket a t p -> Ptr b -> CSize -> MsgFlags -> Ptr a -> Ptr CInt -> IO CInt
unsafeRecvFrom (Socket mfd) bufPtr bufSize flags addrPtr addrSizePtr = do
fix $ \again-> do
ewb <- withMVar mfd $ \fd-> do
when (fd < 0) $ do
throwIO (SocketException eBADF)
fix $ \retry-> do
i <- c_recvfrom fd bufPtr bufSize flags addrPtr addrSizePtr
if (i < 0) then do
e <- getErrno
if e == eWOULDBLOCK || e == eAGAIN then do
threadWaitRead' fd >>= return . Left
else if e == eINTR
then retry
else throwIO (SocketException e)
else return (Right i)
case ewb of
Left wait -> wait >> again
Right bytesReceived -> return (fromIntegral bytesReceived)