module System.Posix.Socket
(
Socket
, withSocketFd
, unsafeSocketFd
, unsafeSocketFromFd
, SockFamily(..)
, SockAddr(..)
, SockType(..)
, pattern SOCK_STREAM
, pattern SOCK_DGRAM
, pattern SOCK_RAW
, pattern SOCK_RDM
, pattern SOCK_SEQPACKET
, SockProto(..)
, defaultSockProto
, SockOpt(..)
, SO_ERROR
, pattern SO_ERROR
, SO_KEEPALIVE
, pattern SO_KEEPALIVE
, SO_REUSEADDR
, pattern SO_REUSEADDR
, SockOps(..)
, MsgFlags(..)
, pattern MSG_PEEK
, pattern MSG_TRUNC
, pattern MSG_OOB
, pattern MSG_DONTROUTE
, socket
, getSockOpt
, setSockOpt
, bind
, connect
, tryConnect
, listen
, accept
, tryAccept
, getLocalAddr
, getRemoteAddr
, hasOobData
, recvBufs
, recvBuf
, recv'
, recv
, recvBufsFrom
, recvBufFrom
, recvFrom'
, recvFrom
, sendBufs
, sendMany'
, sendMany
, sendBuf
, send'
, send
, sendBufsTo
, sendManyTo'
, sendManyTo
, sendBufTo
, sendTo'
, sendTo
, pattern SHUT_RD
, pattern SHUT_WR
, pattern SHUT_RDWR
, shutdown
, close
) where
import Data.Typeable (Typeable)
import Data.Proxy (Proxy(..))
import Data.Word
import Data.Bits ((.|.))
import Data.Default.Class
import Data.List (partition)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Internal as BS
import qualified Data.ByteString.Unsafe as BS
import Data.Flags (Flags(..), BoundedFlags(..), (.>=.))
import Data.Foldable (forM_)
import Control.Applicative ((<$>))
import Control.Monad (void, when, foldM)
import Control.Monad.Base
import Control.Exception (throwIO)
import Control.Concurrent (threadWaitRead, threadWaitWrite)
import Control.Concurrent.MVar
import Foreign.Storable (Storable(..))
import Foreign.Ptr (Ptr, castPtr, nullPtr, plusPtr)
import Foreign.Marshal.Alloc (alloca, allocaBytesAligned)
import Foreign.Marshal.Utils (with)
import Foreign.C.Types (CInt(..), CSize(..))
import System.Posix.Types (CSsize(..))
import Foreign.C.Error (Errno(..), eOK, eINVAL, eMSGSIZE, eINPROGRESS, eAGAIN,
eWOULDBLOCK, getErrno, errnoToIOError,
throwErrno, throwErrnoIfMinus1, throwErrnoIfMinus1_)
import System.IO.Error (eofErrorType, mkIOError)
import System.Posix.Types (Fd(..))
import System.Posix.IO (closeFd)
import GHC.Conc (closeFdWith)
newtype Socket f = Socket (MVar Fd) deriving (Typeable, Eq)
withSocketFd ∷ MonadBase IO μ ⇒ Socket f → (Fd → IO α) → μ α
withSocketFd (Socket v) f = liftBase $ withMVar v f
unsafeSocketFd ∷ MonadBase IO μ ⇒ Socket f → μ Fd
unsafeSocketFd (Socket v) = liftBase $ readMVar v
unsafeSocketFromFd ∷ MonadBase IO μ ⇒ Fd → μ (Socket f)
unsafeSocketFromFd = liftBase . fmap Socket . newMVar
class SockAddr a where
sockAddrMaxSize ∷ Proxy a → Int
sockAddrSize ∷ a → Int
peekSockAddr ∷ Ptr a
→ Int
→ IO a
pokeSockAddr ∷ Ptr a
→ a
→ IO ()
class SockAddr (SockFamilyAddr f) ⇒ SockFamily f where
type SockFamilyAddr f
sockFamilyCode ∷ Proxy f → CInt
newtype SockType = SockType CInt deriving (Typeable, Eq, Ord, Show, Storable)
pattern SOCK_STREAM ∷ SockType
pattern SOCK_STREAM = SockType 1
pattern SOCK_DGRAM ∷ SockType
pattern SOCK_DGRAM = SockType 2
pattern SOCK_RAW ∷ SockType
pattern SOCK_RAW = SockType 3
pattern SOCK_RDM ∷ SockType
pattern SOCK_RDM = SockType 4
pattern SOCK_SEQPACKET ∷ SockType
pattern SOCK_SEQPACKET = SockType 5
newtype SockProto = SockProto CInt deriving (Typeable, Eq, Ord, Show, Storable)
defaultSockProto ∷ SockProto
defaultSockProto = SockProto 0
instance Default SockProto where
def = defaultSockProto
class Storable (SockOptRaw o) ⇒ SockOpt o where
type SockOptValue o
type SockOptRaw o
type SockOptReadable o ∷ Bool
type SockOptWritable o ∷ Bool
sockOptRaw ∷ Proxy o → SockOptValue o → SockOptRaw o
sockOptValue ∷ Proxy o → SockOptRaw o → SockOptValue o
sockOptLevel ∷ Proxy o → CInt
sockOptCode ∷ Proxy o → CInt
data SO_ERROR deriving Typeable
pattern SO_ERROR ∷ Proxy SO_ERROR
pattern SO_ERROR = Proxy
instance SockOpt SO_ERROR where
type SockOptValue SO_ERROR = Errno
type SockOptRaw SO_ERROR = CInt
type SockOptReadable SO_ERROR = 'True
type SockOptWritable SO_ERROR = 'False
sockOptRaw _ (Errno e) = e
sockOptValue _ = Errno
sockOptLevel _ = 1
sockOptCode _ = 4
data SO_KEEPALIVE deriving Typeable
pattern SO_KEEPALIVE ∷ Proxy SO_KEEPALIVE
pattern SO_KEEPALIVE = Proxy
instance SockOpt SO_KEEPALIVE where
type SockOptValue SO_KEEPALIVE = Bool
type SockOptRaw SO_KEEPALIVE = CInt
type SockOptReadable SO_KEEPALIVE = 'True
type SockOptWritable SO_KEEPALIVE = 'True
sockOptRaw _ False = 0
sockOptRaw _ True = 1
sockOptValue _ = (/= 0)
sockOptLevel _ = 1
sockOptCode _ = 9
data SO_REUSEADDR deriving Typeable
pattern SO_REUSEADDR ∷ Proxy SO_REUSEADDR
pattern SO_REUSEADDR = Proxy
instance SockOpt SO_REUSEADDR where
type SockOptValue SO_REUSEADDR = Bool
type SockOptRaw SO_REUSEADDR = CInt
type SockOptReadable SO_REUSEADDR = 'True
type SockOptWritable SO_REUSEADDR = 'True
sockOptRaw _ False = 0
sockOptRaw _ True = 1
sockOptValue _ = (/= 0)
sockOptLevel _ = 1
sockOptCode _ = 2
data SockOps = NoSockOps
| RecvSockOps
| SendSockOps
| AllSockOps
deriving (Typeable, Show, Read, Eq)
instance Flags SockOps where
noFlags = NoSockOps
andFlags NoSockOps ops = ops
andFlags ops NoSockOps = ops
andFlags ops1 ops2 | ops1 == ops2 = ops1
andFlags _ _ = AllSockOps
butFlags _ AllSockOps = NoSockOps
butFlags ops1 ops2 | ops1 == ops2 = NoSockOps
butFlags ops _ = ops
commonFlags AllSockOps ops = ops
commonFlags ops AllSockOps = ops
commonFlags ops1 ops2 | ops1 == ops2 = ops1
commonFlags _ _ = NoSockOps
instance BoundedFlags SockOps where
allFlags = AllSockOps
enumFlags f = filter (f .>=.) [RecvSockOps, SendSockOps]
newtype MsgFlags = MsgFlags CInt deriving (Typeable, Eq, Show, Storable, Flags)
pattern MSG_PEEK ∷ MsgFlags
pattern MSG_PEEK = MsgFlags 2
pattern MSG_TRUNC ∷ MsgFlags
pattern MSG_TRUNC = MsgFlags 32
pattern MSG_OOB ∷ MsgFlags
pattern MSG_OOB = MsgFlags 1
pattern MSG_DONTROUTE ∷ MsgFlags
pattern MSG_DONTROUTE = MsgFlags 4
allocaMaxAddr ∷ SockAddr a ⇒ Proxy a → (Ptr a → Word32 → IO α) → IO α
allocaMaxAddr addrProxy f =
allocaBytesAligned size 2 $
(`f` (fromIntegral size))
where size = sockAddrMaxSize addrProxy
allocaAddr ∷ SockAddr a ⇒ a → (Ptr a → Word32 → IO α) → IO α
allocaAddr addr f =
allocaBytesAligned size 2 $
(`f` (fromIntegral size))
where size = sockAddrSize addr
peekAddrOfSize ∷ SockFamily f
⇒ Proxy f → Ptr (SockFamilyAddr f) → Ptr Word32
→ IO (SockFamilyAddr f)
peekAddrOfSize fam p pSize = do
outSize ← fromIntegral <$> peek pSize
famCode ∷ Word16 ← (\hsc_ptr -> peekByteOff hsc_ptr 0) p
when (fromIntegral famCode /= sockFamilyCode fam) $
ioError $ userError "Invalid socket address family"
peekSockAddr p outSize
withAddr ∷ SockFamily f
⇒ Proxy f
→ SockFamilyAddr f
→ (Ptr (SockFamilyAddr f) → Word32 → IO α)
→ IO α
withAddr fam addr f =
allocaAddr addr $ \p size → do
pokeSockAddr p addr
(\hsc_ptr -> pokeByteOff hsc_ptr 0) p famCode
f p size
where famCode ∷ Word16
famCode = fromIntegral $ sockFamilyCode fam
socket ∷ (SockFamily f, MonadBase IO μ)
⇒ Proxy f → SockType → SockProto → μ (Socket f)
socket f (SockType t) p = liftBase $ do
fd ← throwErrnoIfMinus1 "socket" $
c_socket (sockFamilyCode f)
(t .|. 2048) p
fmap Socket $ newMVar $ Fd fd
getFdOpt ∷ ∀ o . (SockOpt o, SockOptReadable o ~ 'True)
⇒ Fd → Proxy o → IO (SockOptValue o)
getFdOpt fd o =
alloca $ \p →
with (fromIntegral $ sizeOf (undefined ∷ SockOptRaw o)) $ \pSize → do
throwErrnoIfMinus1_ "getSockOpt" $
c_getsockopt fd (sockOptLevel o) (sockOptCode o) p pSize
sockOptValue o <$> peek p
getSockOpt ∷ (SockOpt o, SockOptReadable o ~ 'True, MonadBase IO μ)
⇒ Socket f → Proxy o → μ (SockOptValue o)
getSockOpt s o = withSocketFd s $ \fd → getFdOpt fd o
setSockOpt ∷ (SockOpt o, SockOptWritable o ~ 'True, MonadBase IO μ)
⇒ Socket f → Proxy o → SockOptValue o → μ ()
setSockOpt s o v = withSocketFd s $ \fd →
with raw $ \p →
throwErrnoIfMinus1_ "setSockOpt" $
c_setsockopt fd (sockOptLevel o) (sockOptCode o) p $
fromIntegral (sizeOf raw)
where raw = sockOptRaw o v
bind ∷ ∀ f μ . (SockFamily f, MonadBase IO μ)
⇒ Socket f → SockFamilyAddr f → μ ()
bind s addr = withSocketFd s $ \fd →
withAddr (Proxy ∷ Proxy f) addr $ \p size →
throwErrnoIfMinus1_ "bind" $ c_bind fd p $ fromIntegral size
connect ∷ ∀ f μ . (SockFamily f, MonadBase IO μ)
⇒ Socket f → SockFamilyAddr f → μ ()
connect s addr = withSocketFd s $ \fd →
withAddr (Proxy ∷ Proxy f) addr $ \p size →
doConnect fd p $ fromIntegral size
where doConnect fd p size = do
r ← c_connect fd p size
if r == 1 then do
errno ← getErrno
case errno of
e | e == eINPROGRESS → do
threadWaitWrite fd
errno' ← getFdOpt fd SO_ERROR
when (errno' /= eOK) $
throwIO $ errnoToIOError "connect" errno' Nothing Nothing
_ → throwErrno "connect"
else
return ()
tryConnect ∷ ∀ f μ . (SockFamily f, MonadBase IO μ)
⇒ Socket f → SockFamilyAddr f → μ Bool
tryConnect s addr = withSocketFd s $ \fd →
withAddr (Proxy ∷ Proxy f) addr $ \p size → do
r ← c_connect fd p $ fromIntegral size
if r == 1
then do
errno ← getErrno
if errno == eINPROGRESS
then return False
else throwErrno "connect"
else
return True
listen ∷ MonadBase IO μ ⇒ Socket f → Int → μ ()
listen s backlog = withSocketFd s $ \fd →
throwErrnoIfMinus1_ "listen" $ c_listen fd $ fromIntegral backlog
accept ∷ ∀ f μ . (SockFamily f, MonadBase IO μ)
⇒ Socket f → μ (Socket f, SockFamilyAddr f)
accept s = withSocketFd s $ \fd →
allocaMaxAddr (Proxy ∷ Proxy (SockFamilyAddr f)) $ \p size →
with size $ \pSize → doAccept fd p pSize
where doAccept fd p pSize = do
cfd ← c_accept fd p pSize
2048
if cfd == 1 then do
errno ← getErrno
case errno of
e | e == eAGAIN || e == eWOULDBLOCK → do
threadWaitRead fd
doAccept fd p pSize
_ → throwErrno "accept"
else do
addr ← peekAddrOfSize (Proxy ∷ Proxy f) p pSize
let accFd = Fd cfd
(, addr) <$> unsafeSocketFromFd accFd
tryAccept ∷ ∀ f μ . (SockFamily f, MonadBase IO μ)
⇒ Socket f → μ (Maybe (Socket f, SockFamilyAddr f))
tryAccept s = withSocketFd s $ \fd →
allocaMaxAddr (Proxy ∷ Proxy (SockFamilyAddr f)) $ \p size →
with size $ \pSize → do
cfd ← c_accept fd p pSize
2048
if cfd == 1 then do
errno ← getErrno
case errno of
e | e == eAGAIN || e == eWOULDBLOCK → return Nothing
_ → throwErrno "accept"
else do
addr ← peekAddrOfSize (Proxy ∷ Proxy f) p pSize
let accFd = Fd cfd
Just . (, addr) <$> unsafeSocketFromFd accFd
getLocalAddr ∷ ∀ f μ . (SockFamily f, MonadBase IO μ)
⇒ Socket f → μ (SockFamilyAddr f)
getLocalAddr s = withSocketFd s $ \fd →
allocaMaxAddr (Proxy ∷ Proxy (SockFamilyAddr f)) $ \p size →
with size $ \pSize → do
throwErrnoIfMinus1_ "getLocalAddr" $ c_getsockname fd p pSize
peekAddrOfSize (Proxy ∷ Proxy f) p pSize
getRemoteAddr ∷ ∀ f μ . (SockFamily f, MonadBase IO μ)
⇒ Socket f → μ (SockFamilyAddr f)
getRemoteAddr s = withSocketFd s $ \fd →
allocaMaxAddr (Proxy ∷ Proxy (SockFamilyAddr f)) $ \p size →
with size $ \pSize → do
throwErrnoIfMinus1_ "getRemoteAddr" $ c_getpeername fd p pSize
peekAddrOfSize (Proxy ∷ Proxy f) p pSize
hasOobData ∷ MonadBase IO μ ⇒ Socket f → μ Bool
hasOobData s = withSocketFd s $ \fd →
fmap (== 1) $ throwErrnoIfMinus1 "hasOOBData" $ c_sockatmark fd
throwCustomErrno ∷ String → Errno → IO α
throwCustomErrno loc errno =
throwIO $ errnoToIOError loc errno Nothing Nothing
throwInval ∷ String → IO α
throwInval loc = throwCustomErrno loc eINVAL
recvBufsFromFd ∷ ∀ f . SockFamily f
⇒ Proxy f → Fd → [(Ptr Word8, Int)] → MsgFlags
→ IO (Maybe (SockFamilyAddr f), Int, MsgFlags)
recvBufsFromFd _ fd bufs' flags = do
let (bufs, bufs'') = partition ((> 0) . snd) bufs'
nn = length bufs
when (any ((< 0) . snd) bufs'' || nn == 0) $ throwInval "recv"
when (nn > 1024) $ throwCustomErrno "recv" eMSGSIZE
allocaBytesAligned (56)
8 $ \pHdr →
allocaMaxAddr (Proxy ∷ Proxy (SockFamilyAddr f)) $ \pAddr addrLen → do
(\hsc_ptr -> pokeByteOff hsc_ptr 0) pHdr pAddr
(\hsc_ptr -> pokeByteOff hsc_ptr 8) pHdr addrLen
let doRecv = do
r ← c_recvmsg fd pHdr flags
case r of
(1) → do
errno ← getErrno
case errno of
e | e == eAGAIN || e == eWOULDBLOCK → do
threadWaitRead fd
doRecv
_ → throwErrno "recv"
0 → throwIO $ mkIOError eofErrorType "recv" Nothing Nothing
_ → do
addrLen' ← (\hsc_ptr -> peekByteOff hsc_ptr 8) pHdr ∷
IO Word32
addr ← if addrLen' == 0
then return Nothing
else fmap Just $ peekSockAddr pAddr $
fromIntegral addrLen'
flags' ← (\hsc_ptr -> peekByteOff hsc_ptr 48) pHdr
return (addr, fromIntegral r, flags')
allocaBytesAligned (nn * (16))
8 $ \pIoVs → do
void . ($ bufs) . ($ pIoVs) . foldM $ \pIoV (p, n) → do
(\hsc_ptr -> pokeByteOff hsc_ptr 0) pIoV p
(\hsc_ptr -> pokeByteOff hsc_ptr 8) pIoV (fromIntegral n ∷ CSize)
return $ plusPtr pIoV (16)
(\hsc_ptr -> pokeByteOff hsc_ptr 16) pHdr pIoVs
(\hsc_ptr -> pokeByteOff hsc_ptr 24) pHdr (fromIntegral nn ∷ CSize)
(\hsc_ptr -> pokeByteOff hsc_ptr 32) pHdr nullPtr
(\hsc_ptr -> pokeByteOff hsc_ptr 40) pHdr (0 ∷ CSize)
(\hsc_ptr -> pokeByteOff hsc_ptr 48) pHdr (0 ∷ CInt)
doRecv
recvBufsFrom' ∷ ∀ f μ . (SockFamily f, MonadBase IO μ)
⇒ Socket f → [(Ptr Word8, Int)] → MsgFlags
→ μ (Maybe (SockFamilyAddr f), Int, MsgFlags)
recvBufsFrom' s bufs flags = withSocketFd s $ \fd →
recvBufsFromFd (Proxy ∷ Proxy f) fd bufs flags
recvBufs ∷ (SockFamily f, MonadBase IO μ)
⇒ Socket f
→ [(Ptr Word8, Int)]
→ MsgFlags
→ μ (Int, MsgFlags)
recvBufs s bufs flags = do
(_, r, flags') ← recvBufsFrom' s bufs flags
return (r, flags')
recvBuf ∷ (SockFamily f, MonadBase IO μ)
⇒ Socket f
→ Ptr α
→ Int
→ MsgFlags
→ μ (Int, MsgFlags)
recvBuf s p len flags = recvBufs s [(castPtr p, len)] flags
recv' ∷ (SockFamily f, MonadBase IO μ)
⇒ Socket f
→ Int
→ MsgFlags
→ μ (ByteString, MsgFlags)
recv' s len flags =
liftBase $ BS.createAndTrim' len $ \p → do
(r, flags') ← recvBuf s p len flags
return (0, r, flags')
recv ∷ (SockFamily f, MonadBase IO μ)
⇒ Socket f
→ Int
→ μ ByteString
recv s len = fst <$> recv' s len noFlags
recvBufsFrom ∷ ∀ f μ . (SockFamily f, MonadBase IO μ)
⇒ Socket f
→ [(Ptr Word8, Int)]
→ MsgFlags
→ μ (SockFamilyAddr f, Int, MsgFlags)
recvBufsFrom s bufs flags = withSocketFd s $ \fd → do
(mAddr, n, flags') ← recvBufsFromFd (Proxy ∷ Proxy f) fd bufs flags
let getpeername =
allocaMaxAddr (Proxy ∷ Proxy (SockFamilyAddr f)) $ \p size →
with size $ \pSize → do
throwErrnoIfMinus1_ "recv" $ c_getpeername fd p pSize
peekAddrOfSize (Proxy ∷ Proxy f) p pSize
(, n, flags') <$> maybe getpeername return mAddr
recvBufFrom ∷ (SockFamily f, MonadBase IO μ)
⇒ Socket f
→ Ptr α
→ Int
→ MsgFlags
→ μ (SockFamilyAddr f, Int, MsgFlags)
recvBufFrom s p len flags = recvBufsFrom s [(castPtr p, len)] flags
recvFrom' ∷ (SockFamily f, MonadBase IO μ)
⇒ Socket f
→ Int
→ MsgFlags
→ μ (SockFamilyAddr f, ByteString, MsgFlags)
recvFrom' s len flags = liftBase $ do
(bs, (addr, flags')) ← BS.createAndTrim' len $ \p → do
(addr, len', flags') ← recvBufFrom s p len flags
return (0, len', (addr, flags'))
return (addr, bs, flags')
recvFrom ∷ (SockFamily f, MonadBase IO μ)
⇒ Socket f
→ Int
→ μ (SockFamilyAddr f, ByteString)
recvFrom s len = do
(addr, bs, _) ← recvFrom' s len noFlags
return (addr, bs)
_sendBufs ∷ ∀ f μ . (SockFamily f, MonadBase IO μ)
⇒ Socket f → [(Ptr Word8, Int)] → MsgFlags
→ Maybe (SockFamilyAddr f) → μ Int
_sendBufs s bufs' flags mAddr = withSocketFd s $ \fd → do
let (bufs, bufs'') = partition ((> 0) . snd) bufs'
nn = length bufs
when (any ((< 0) . snd) bufs'') $ throwInval "send"
when (nn > 1024) $ throwCustomErrno "send" eMSGSIZE
if nn == 0 then return 0
else allocaBytesAligned (56)
8 $ \pHdr → do
let doSend = do
r ← c_sendmsg fd pHdr flags
if r == 1 then do
errno ← getErrno
case errno of
e | e == eAGAIN || e == eWOULDBLOCK → do
threadWaitWrite fd
doSend
_ → throwErrno "send"
else
return $ fromIntegral r
let cont = allocaBytesAligned (nn * (16))
8 $ \pIoVs → do
void . ($ bufs) . ($ pIoVs) . foldM $ \pIoV (p, n) → do
(\hsc_ptr -> pokeByteOff hsc_ptr 0) pIoV p
(\hsc_ptr -> pokeByteOff hsc_ptr 8) pIoV (fromIntegral n ∷ CSize)
return $ plusPtr pIoV (16)
(\hsc_ptr -> pokeByteOff hsc_ptr 16) pHdr pIoVs
(\hsc_ptr -> pokeByteOff hsc_ptr 24) pHdr (fromIntegral nn ∷ CSize)
(\hsc_ptr -> pokeByteOff hsc_ptr 32) pHdr nullPtr
(\hsc_ptr -> pokeByteOff hsc_ptr 40) pHdr (0 ∷ CSize)
(\hsc_ptr -> pokeByteOff hsc_ptr 48) pHdr (0 ∷ CInt)
doSend
case mAddr of
Just addr →
withAddr (Proxy ∷ Proxy f) addr $ \pAddr addrLen → do
(\hsc_ptr -> pokeByteOff hsc_ptr 0) pHdr pAddr
(\hsc_ptr -> pokeByteOff hsc_ptr 8) pHdr addrLen
cont
Nothing → do
(\hsc_ptr -> pokeByteOff hsc_ptr 0) pHdr nullPtr
(\hsc_ptr -> pokeByteOff hsc_ptr 8) pHdr (0 ∷ Word32)
cont
sendBufs ∷ (SockFamily f, MonadBase IO μ)
⇒ Socket f
→ [(Ptr Word8, Int)]
→ MsgFlags
→ μ Int
sendBufs s bufs flags = _sendBufs s bufs flags Nothing
withBufs ∷ [ByteString] → ([(Ptr Word8, Int)] → IO α) → IO α
withBufs bss f = go bss []
where go [] rbufs = f (reverse rbufs)
go (bs : bss') rbufs = BS.unsafeUseAsCStringLen bs $ \(p, len) →
go bss' ((castPtr p, len) : rbufs)
sendMany' ∷ (SockFamily f, MonadBase IO μ)
⇒ Socket f
→ [ByteString]
→ MsgFlags
→ μ Int
sendMany' s bss flags =
liftBase $ withBufs bss $ \bufs → sendBufs s bufs flags
sendMany ∷ (SockFamily f, MonadBase IO μ)
⇒ Socket f
→ [ByteString]
→ μ Int
sendMany s bss = sendMany' s bss noFlags
sendBuf ∷ (SockFamily f, MonadBase IO μ)
⇒ Socket f
→ Ptr α
→ Int
→ MsgFlags
→ μ Int
sendBuf s p len flags = sendBufs s [(castPtr p, len)] flags
send' ∷ (SockFamily f, MonadBase IO μ)
⇒ Socket f
→ ByteString
→ MsgFlags
→ μ Int
send' s bs flags = liftBase $ BS.unsafeUseAsCStringLen bs $ \(p, len) →
sendBuf s p len flags
send ∷ (SockFamily f, MonadBase IO μ)
⇒ Socket f
→ ByteString
→ μ Int
send s bs = send' s bs noFlags
sendBufsTo ∷ (SockFamily f, MonadBase IO μ)
⇒ Socket f
→ [(Ptr Word8, Int)]
→ MsgFlags
→ SockFamilyAddr f
→ μ Int
sendBufsTo s bufs flags addr = _sendBufs s bufs flags (Just addr)
sendManyTo' ∷ (SockFamily f, MonadBase IO μ)
⇒ Socket f
→ [ByteString]
→ MsgFlags
→ SockFamilyAddr f
→ μ Int
sendManyTo' s bss flags addr = liftBase $ withBufs bss $ \bufs →
sendBufsTo s bufs flags addr
sendManyTo ∷ (SockFamily f, MonadBase IO μ)
⇒ Socket f
→ [ByteString]
→ SockFamilyAddr f
→ μ Int
sendManyTo s bss addr = sendManyTo' s bss noFlags addr
sendBufTo ∷ (SockFamily f, MonadBase IO μ)
⇒ Socket f
→ Ptr α
→ Int
→ MsgFlags
→ SockFamilyAddr f
→ μ Int
sendBufTo s p len flags addr = sendBufsTo s [(castPtr p, len)] flags addr
sendTo' ∷ (SockFamily f, MonadBase IO μ)
⇒ Socket f
→ ByteString
→ MsgFlags
→ SockFamilyAddr f
→ μ Int
sendTo' s bs flags addr =
liftBase $ BS.unsafeUseAsCStringLen bs $ \(p, len) →
sendBufTo s p len flags addr
sendTo ∷ (SockFamily f, MonadBase IO μ)
⇒ Socket f
→ ByteString
→ SockFamilyAddr f
→ μ Int
sendTo s bs addr = sendTo' s bs noFlags addr
pattern SHUT_RD ∷ SockOps
pattern SHUT_RD = RecvSockOps
pattern SHUT_WR ∷ SockOps
pattern SHUT_WR = SendSockOps
pattern SHUT_RDWR ∷ SockOps
pattern SHUT_RDWR = AllSockOps
shutdown ∷ MonadBase IO μ ⇒ Socket f → SockOps → μ ()
shutdown s dirs = withSocketFd s $ \fd →
forM_ how $ throwErrnoIfMinus1_ "shutdown" . c_shutdown fd
where how = if dirs .>=. SendSockOps then
if dirs .>=. RecvSockOps then
Just 2
else
Just 1
else
if dirs .>=. RecvSockOps then
Just 0
else
Nothing
close ∷ MonadBase IO μ ⇒ Socket f → μ ()
close (Socket v) = liftBase $ modifyMVar_ v $ \fd → do
when (fd >= 0) $ closeFdWith closeFd fd
return (1)
foreign import ccall "socket"
c_socket ∷ CInt → CInt → SockProto → IO CInt
foreign import ccall "getsockopt"
c_getsockopt ∷ Fd → CInt → CInt → Ptr α → Ptr Word32 → IO CInt
foreign import ccall "setsockopt"
c_setsockopt ∷ Fd → CInt → CInt → Ptr α → Word32 → IO CInt
foreign import ccall "bind"
c_bind ∷ Fd → Ptr α → Word32 → IO CInt
foreign import ccall "connect"
c_connect ∷ Fd → Ptr α → Word32 → IO CInt
foreign import ccall "listen"
c_listen ∷ Fd → CInt → IO CInt
foreign import ccall "accept4"
c_accept ∷ Fd → Ptr α → Ptr Word32 → CInt → IO CInt
foreign import ccall "getsockname"
c_getsockname ∷ Fd → Ptr α → Ptr Word32 → IO CInt
foreign import ccall "getpeername"
c_getpeername ∷ Fd → Ptr α → Ptr Word32 → IO CInt
foreign import ccall "sockatmark"
c_sockatmark ∷ Fd → IO CInt
foreign import ccall "recvmsg"
c_recvmsg ∷ Fd → Ptr β → MsgFlags → IO CSsize
foreign import ccall "sendmsg"
c_sendmsg ∷ Fd → Ptr β → MsgFlags → IO CSsize
foreign import ccall "shutdown"
c_shutdown ∷ Fd → CInt → IO CInt