on master help sign in
Add bracketing operations (withServerAddr) for clients
687646aHarendra Kumar
src/Streamly/Internal/Network/Inet/TCP.hs+57−16
@@ -32,10 +32,16 @@ module Streamly.Internal.Network.Inet.TCP
32 , connectionsOnLocalHost
32 , connectionsOnLocalHost
33
33
34 -- * TCP clients
34 -- * TCP clients
35− -- | Socket based reads and writes.
35+ -- | IP Address based operations.
36− , withConnection
36+ , connect
37+ , withServerAddrM
38+
39+ -- ** Unfolds
40+ , withServerAddr
37
41
42+ -- ** Streams
43+ , withConnection
38− -- ** Source
44+ -- *** Source
39 , read
45 , read
40 -- , readUtf8
46 -- , readUtf8
41 -- , readLines
47 -- , readLines
@@ -50,7 +56,7 @@ module Streamly.Internal.Network.Inet.TCP
50 -- , readArraysOf
56 -- , readArraysOf
51 -- , readArrays
57 -- , readArrays
52
58
53− -- ** Sink
59+ -- *** Sink
54 , write
60 , write
55 -- , writeUtf8
61 -- , writeUtf8
56 -- , writeUtf8ByLines
62 -- , writeUtf8ByLines
@@ -84,13 +90,13 @@ module Streamly.Internal.Network.Inet.TCP
84 )
90 )
85where
91where
86
92
87−import Control.Monad.Catch (MonadCatch)
93+import Control.Monad.Catch (MonadCatch, MonadMask, bracket)
88import Control.Monad.IO.Class (MonadIO(..))
94import Control.Monad.IO.Class (MonadIO(..))
89import Data.Word (Word8)
95import Data.Word (Word8)
90import Network.Socket
96import Network.Socket
91 (Socket, PortNumber, SocketOption(..), Family(..), SockAddr(..),
97 (Socket, PortNumber, SocketOption(..), Family(..), SockAddr(..),
92 SocketType(..), defaultProtocol, maxListenQueue, tupleToHostAddress,
98 SocketType(..), defaultProtocol, maxListenQueue, tupleToHostAddress,
93− socket, connect)
99+ socket)
94import Prelude hiding (read)
100import Prelude hiding (read)
95
101
96import Streamly (MonadAsync)
102import Streamly (MonadAsync)
@@ -110,7 +116,7 @@ import qualified Streamly.Network.Socket as SK
110import qualified Streamly.Internal.Network.Socket as ISK
116import qualified Streamly.Internal.Network.Socket as ISK
111
117
112-------------------------------------------------------------------------------
118-------------------------------------------------------------------------------
113−-- TCP Servers
119+-- Accept (unfolds)
114-------------------------------------------------------------------------------
120-------------------------------------------------------------------------------
115
121
116-- | Unfold a tuple @(ipAddr, port)@ into a stream of connected TCP sockets.
122-- | Unfold a tuple @(ipAddr, port)@ into a stream of connected TCP sockets.
@@ -158,7 +164,7 @@ acceptOnPortLocal :: MonadIO m => Unfold m PortNumber Socket
158acceptOnPortLocal = UF.supplyFirst acceptOnAddr (127,0,0,1)
164acceptOnPortLocal = UF.supplyFirst acceptOnAddr (127,0,0,1)
159
165
160-------------------------------------------------------------------------------
166-------------------------------------------------------------------------------
161−-- Listen
167+-- Accept (streams)
162-------------------------------------------------------------------------------
168-------------------------------------------------------------------------------
163
169
164-- | Like 'connections' but binds on the specified IPv4 address of the machine
170-- | Like 'connections' but binds on the specified IPv4 address of the machine
@@ -206,15 +212,50 @@ connectionsOnLocalHost = connectionsOnAddr (127,0,0,1)
206-- TCP Clients
212-- TCP Clients
207-------------------------------------------------------------------------------
213-------------------------------------------------------------------------------
208
214
215+-- | Connect to the specified IP address and port number.
216+--
217+-- /Internal/
218+connect :: (Word8, Word8, Word8, Word8) -> PortNumber -> IO Socket
219+connect addr port = do
220+ sock <- socket AF_INET Stream defaultProtocol
221+ Net.connect sock $ SockAddrInet port (Net.tupleToHostAddress addr)
222+ return sock
223+
224+-- | Connect to a remote host using IP address and port and run the supplied
225+-- action on the resulting socket. 'withServerAddrM' makes sure that the
226+-- socket is closed on normal termination or in case of an exception. If
227+-- closing the socket raises an exception, then this exception will be raised
228+-- by 'withServerAddrM'.
229+--
230+-- @since 0.7.0
231+{-# INLINABLE withServerAddrM #-}
232+withServerAddrM :: (MonadMask m, MonadIO m)
233+ => (Word8, Word8, Word8, Word8) -> PortNumber -> (Socket -> m ()) -> m ()
234+withServerAddrM addr port =
235+ bracket (liftIO $ connect addr port) (liftIO . Net.close)
236+
209-------------------------------------------------------------------------------
237-------------------------------------------------------------------------------
210−-- Connect
238+-- Connect (unfolds)
211-------------------------------------------------------------------------------
239-------------------------------------------------------------------------------
212
240
241+-- | Transform an 'Unfold' from a 'Socket' to an unfold from a remote IP
242+-- address and port. The resulting unfold opens a socket, uses it using the
243+-- supplied unfold and then makes sure that the socket is closed on normal
244+-- termination or in case of an exception. If closing the socket raises an
245+-- exception, then this exception will be raised by 'withServerAddr'.
246+--
247+-- @since 0.7.0
248+{-# INLINABLE withServerAddr #-}
249+withServerAddr :: (MonadCatch m, MonadIO m)
250+ => Unfold m Socket a
213−openConnection :: (Word8, Word8, Word8, Word8) -> PortNumber -> IO Socket
251+ -> Unfold m ((Word8, Word8, Word8, Word8), PortNumber) a
214−openConnection addr port = do
252+withServerAddr =
215− sock <- socket AF_INET Stream defaultProtocol
253+ UF.bracket (\(addr, port) -> liftIO $ connect addr port)
216− connect sock $ SockAddrInet port (Net.tupleToHostAddress addr)
254+ (liftIO . Net.close)
217− return sock
255+
256+-------------------------------------------------------------------------------
257+-- Connect (streams)
258+-------------------------------------------------------------------------------
218
259
219-- | @'withConnection' addr port act@ opens a connection to the specified IPv4
260-- | @'withConnection' addr port act@ opens a connection to the specified IPv4
220-- host address and port and passes the resulting socket handle to the
261-- host address and port and passes the resulting socket handle to the
@@ -228,7 +269,7 @@ openConnection addr port = do
228withConnection :: (IsStream t, MonadCatch m, MonadIO m)
269withConnection :: (IsStream t, MonadCatch m, MonadIO m)
229 => (Word8, Word8, Word8, Word8) -> PortNumber -> (Socket -> t m a) -> t m a
270 => (Word8, Word8, Word8, Word8) -> PortNumber -> (Socket -> t m a) -> t m a
230withConnection addr port =
271withConnection addr port =
231− S.bracket (liftIO $ openConnection addr port) (liftIO . Net.close)
272+ S.bracket (liftIO $ connect addr port) (liftIO . Net.close)
232
273
233-------------------------------------------------------------------------------
274-------------------------------------------------------------------------------
234-- Read Addr to Stream
275-- Read Addr to Stream
@@ -275,7 +316,7 @@ writeArrays
275writeArrays addr port = Fold step initial extract
316writeArrays addr port = Fold step initial extract
276 where
317 where
277 initial = do
318 initial = do
278− skt <- liftIO (openConnection addr port)
319+ skt <- liftIO (connect addr port)
279 FL.initialize (SK.writeArrays skt)
320 FL.initialize (SK.writeArrays skt)
280 step = FL.runStep
321 step = FL.runStep
281 extract (Fold _ initial1 extract1) = initial1 >>= extract1
322 extract (Fold _ initial1 extract1) = initial1 >>= extract1