on master help sign in
Add bracketing operations (withServerAddr) for clients
commit687646aeb66863c641718ad82f4bdc91b886d47e authorHarendra Kumar <harendra.kumar@gmail.com> dateMon 14 Oct 2019, 17:12 (7 years ago) parent3c5c6a0
1 file changed+57−16
src/Streamly/Internal/Network/Inet/TCP.hs+57−16
src/Streamly/Internal/Network/Inet/TCP.hs+57−16
@@ -32,10 +32,16 @@ module Streamly.Internal.Network.Inet.TCP
3232 , connectionsOnLocalHost
3333
3434 -- * TCP clients
35− -- | Socket based reads and writes.
36− , withConnection
35+ -- | IP Address based operations.
36+ , connect
37+ , withServerAddrM
38+
39+ -- ** Unfolds
40+ , withServerAddr
3741
38− -- ** Source
42+ -- ** Streams
43+ , withConnection
44+ -- *** Source
3945 , read
4046 -- , readUtf8
4147 -- , readLines
@@ -50,7 +56,7 @@ module Streamly.Internal.Network.Inet.TCP
5056 -- , readArraysOf
5157 -- , readArrays
5258
53− -- ** Sink
59+ -- *** Sink
5460 , write
5561 -- , writeUtf8
5662 -- , writeUtf8ByLines
@@ -84,13 +90,13 @@ module Streamly.Internal.Network.Inet.TCP
8490 )
8591where
8692
87−import Control.Monad.Catch (MonadCatch)
93+import Control.Monad.Catch (MonadCatch, MonadMask, bracket)
8894import Control.Monad.IO.Class (MonadIO(..))
8995import Data.Word (Word8)
9096import Network.Socket
9197 (Socket, PortNumber, SocketOption(..), Family(..), SockAddr(..),
9298 SocketType(..), defaultProtocol, maxListenQueue, tupleToHostAddress,
93− socket, connect)
99+ socket)
94100import Prelude hiding (read)
95101
96102import Streamly (MonadAsync)
@@ -110,7 +116,7 @@ import qualified Streamly.Network.Socket as SK
110116import qualified Streamly.Internal.Network.Socket as ISK
111117
112118-------------------------------------------------------------------------------
113−-- TCP Servers
119+-- Accept (unfolds)
114120-------------------------------------------------------------------------------
115121
116122-- | Unfold a tuple @(ipAddr, port)@ into a stream of connected TCP sockets.
@@ -158,7 +164,7 @@ acceptOnPortLocal :: MonadIO m => Unfold m PortNumber Socket
158164acceptOnPortLocal = UF.supplyFirst acceptOnAddr (127,0,0,1)
159165
160166-------------------------------------------------------------------------------
161−-- Listen
167+-- Accept (streams)
162168-------------------------------------------------------------------------------
163169
164170-- | Like 'connections' but binds on the specified IPv4 address of the machine
@@ -206,15 +212,50 @@ connectionsOnLocalHost = connectionsOnAddr (127,0,0,1)
206212-- TCP Clients
207213-------------------------------------------------------------------------------
208214
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+
209237-------------------------------------------------------------------------------
210−-- Connect
238+-- Connect (unfolds)
211239-------------------------------------------------------------------------------
212240
213−openConnection :: (Word8, Word8, Word8, Word8) -> PortNumber -> IO Socket
214−openConnection addr port = do
215− sock <- socket AF_INET Stream defaultProtocol
216− connect sock $ SockAddrInet port (Net.tupleToHostAddress addr)
217− return sock
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
251+ -> Unfold m ((Word8, Word8, Word8, Word8), PortNumber) a
252+withServerAddr =
253+ UF.bracket (\(addr, port) -> liftIO $ connect addr port)
254+ (liftIO . Net.close)
255+
256+-------------------------------------------------------------------------------
257+-- Connect (streams)
258+-------------------------------------------------------------------------------
218259
219260-- | @'withConnection' addr port act@ opens a connection to the specified IPv4
220261-- host address and port and passes the resulting socket handle to the
@@ -228,7 +269,7 @@ openConnection addr port = do
228269withConnection :: (IsStream t, MonadCatch m, MonadIO m)
229270 => (Word8, Word8, Word8, Word8) -> PortNumber -> (Socket -> t m a) -> t m a
230271withConnection addr port =
231− S.bracket (liftIO $ openConnection addr port) (liftIO . Net.close)
272+ S.bracket (liftIO $ connect addr port) (liftIO . Net.close)
232273
233274-------------------------------------------------------------------------------
234275-- Read Addr to Stream
@@ -275,7 +316,7 @@ writeArrays
275316writeArrays addr port = Fold step initial extract
276317 where
277318 initial = do
278− skt <- liftIO (openConnection addr port)
319+ skt <- liftIO (connect addr port)
279320 FL.initialize (SK.writeArrays skt)
280321 step = FL.runStep
281322 extract (Fold _ initial1 extract1) = initial1 >>= extract1