Copyright | (c) Lars Petersen 2015 |
---|---|
License | MIT |
Maintainer | info@lars-petersen.net |
Stability | experimental |
Safe Haskell | None |
Language | Haskell2010 |
- newtype Socket f t p = Socket (MVar Fd)
- unsafeSend :: Socket a t p -> Ptr b -> CSize -> MessageFlags -> IO CInt
- unsafeSendTo :: Socket f t p -> Ptr b -> CSize -> MessageFlags -> Ptr (SocketAddress f) -> CInt -> IO CInt
- unsafeReceive :: Socket a t p -> Ptr b -> CSize -> MessageFlags -> IO CInt
- unsafeReceiveFrom :: Socket f t p -> Ptr b -> CSize -> MessageFlags -> Ptr (SocketAddress f) -> Ptr CInt -> IO CInt
- unsafeGetSocketOption :: Storable a => Socket f t p -> CInt -> CInt -> IO a
- unsafeSetSocketOption :: Storable a => Socket f t p -> CInt -> CInt -> a -> IO ()
- unsafeSocketWaitRead :: Fd -> Int -> IO (IO ())
- unsafeSocketWaitWrite :: Fd -> Int -> IO (IO ())
- tryWaitRetryLoop :: Socket f t p -> (Fd -> Int -> IO (IO ())) -> (Fd -> Ptr CInt -> IO CInt) -> IO CInt
Socket Constructor
A generic socket type. Use socket
to create a new socket.
The socket is just an MVar
-wrapped file descriptor.
The Socket
constructor is exported trough the unsafe
module in order to make this library easily extensible, but it is usually
not necessary nor advised to work directly on the file descriptor.
If you do, the following rules must be obeyed:
- Make sure not to deadlock. Use
withMVar
or similar. - The lock must not be held during a blocking call. This would make it impossible to send and receive simultaneously or to close the socket.
- The lock must be held when calling operations that use the file descriptor. Otherwise the socket might get closed or even reused by another thread/capability which might result in reading from or writing totally different connection. This is a security nightmare!
- The socket is non-blocking and all the code relies on that assumption.
You need to use GHC's eventing mechanism primitives to block until
something happens. The former rules forbid to use
threadWaitRead
as it does not separate between registering the file descriptor (for which the lock must be held) and the actual waiting (for which you must not hold the lock). Also see this thread and read the library code to see how the problem is currently circumvented.
Socket Operations
unsafeSend
unsafeSend :: Socket a t p -> Ptr b -> CSize -> MessageFlags -> IO CInt Source #
unsafeSendTo
unsafeSendTo :: Socket f t p -> Ptr b -> CSize -> MessageFlags -> Ptr (SocketAddress f) -> CInt -> IO CInt Source #
unsafeReceive
unsafeReceive :: Socket a t p -> Ptr b -> CSize -> MessageFlags -> IO CInt Source #
unsafeReceiveFrom
unsafeReceiveFrom :: Socket f t p -> Ptr b -> CSize -> MessageFlags -> Ptr (SocketAddress f) -> Ptr CInt -> IO CInt Source #
Socket Options
unsafeGetSocketOption
unsafeSetSocketOption
Waiting For Events
unsafeSocketWaitRead
:: Fd | Socket descriptor |
-> Int | How many times has it been tried unsuccessfully so far? (currently only relevant on Windows) |
-> IO (IO ()) | The outer action registers the waiting, the inner does the actual wait. |
Blocks until a socket should be tried for reading.
safeSocketWaitRead = do wait <- withMVar msock $ \sock-> do -- Register while holding a lock on the socket descriptor. unsafeSocketWaitRead sock 0 -- Do the waiting without keeping the socket descriptor locked. wait