@@ -23,14 +23,10 @@
24module Streamly.Internal.Network.Server
24module Streamly.Internal.Network.Server
26− -- * Server Configuration
29 -- * TCP Servers
26 -- * TCP Servers
30 -- ** Connected sockets
27 -- ** Connected sockets
31 -- *** Unfolds
28 -- *** Unfolds
33− , listenOnAddr
29+ listenOnAddr
34 , listenOnPort
30 , listenOnPort
35 , listenOnPortLocal
31 , listenOnPortLocal
@@ -68,75 +64,15 @@ import Control.Monad.IO.Class (MonadIO(..))
68import Data.Word (Word8)
64import Data.Word (Word8)
69import Network.Socket
65import Network.Socket
70 (Socket, PortNumber, SocketOption(..), Family(..), SockAddr(..),
66 (Socket, PortNumber, SocketOption(..), Family(..), SockAddr(..),
71− withSocketsDo, SocketType(..), socket, accept, bind,
72− defaultProtocol, setSocketOption, maxListenQueue, tupleToHostAddress)
67+ SocketType(..), defaultProtocol, maxListenQueue, tupleToHostAddress)
73import Prelude hiding (read)
68import Prelude hiding (read)
75−import qualified Network.Socket as Net
77import Streamly (MonadAsync)
70import Streamly (MonadAsync)
78import Streamly.Internal.Data.Unfold.Types (Unfold(..))
71import Streamly.Internal.Data.Unfold.Types (Unfold(..))
72+import Streamly.Internal.Network.Socket (SockSpec(..), listen, connections)
79import Streamly.Streams.Serial (SerialT)
73import Streamly.Streams.Serial (SerialT)
81import qualified Streamly.Internal.Data.Unfold as UF
75import qualified Streamly.Internal.Data.Unfold as UF
82−import qualified Streamly.Prelude as S
83−import qualified Streamly.Streams.StreamD.Type as D
85−-------------------------------------------------------------------------------
87−-------------------------------------------------------------------------------
89−-- | Specify the configuration of a server.
92− serverAddressFamily :: !Family
93− , serverAddress :: !SockAddr
94− , serverSockOpts :: ![(SocketOption, Int)]
97−initListener :: Int -> Server -> IO Socket
98−initListener tcpListenQ Server{..} =
100− sock <- socket serverAddressFamily Stream defaultProtocol
101− mapM_ (\(opt, val) -> setSocketOption sock opt val) serverSockOpts
102− bind sock serverAddress
103− Net.listen sock tcpListenQ
106−{-# INLINE listenTuples #-}
107−listenTuples :: MonadIO m => Unfold m (Int, Server) (Socket, SockAddr)
108−listenTuples = Unfold step inject
110− inject (tcpListenQ, opts) = do
111− listener <- liftIO $ initListener tcpListenQ opts
115− r <- liftIO $ accept listener
116− -- XXX error handling
117− return $ D.Yield r listener
119−-- | Unfold a tuple @(listenQueue, address)@ into a stream of connected
120−-- TCP sockets. @listenQueue@ is the maximum number of pending connections in
121−-- the backlog. @address@ is the server address specification (address
122−-- family, local interface IP address and port).
125−{-# INLINE listen #-}
126−listen :: MonadIO m => Unfold m (Int, Server) Socket
127−listen = UF.map fst listenTuples
129−{-# INLINE listenTuplesOnAddr #-}
132− => Unfold m ((Word8, Word8, Word8, Word8), PortNumber) (Socket, SockAddr)
133−listenTuplesOnAddr = UF.lmap f listenTuples
135− f (addr, port) = (maxListenQueue, Server
136− { serverAddressFamily = AF_INET
137− , serverAddress = SockAddrInet port (tupleToHostAddress addr)
138− , serverSockOpts = [(NoDelay,1), (ReuseAddr,1)]
141-- | Unfold a tuple @(ipAddr, port)@ into a stream of connected TCP sockets.
77-- | Unfold a tuple @(ipAddr, port)@ into a stream of connected TCP sockets.
142-- @ipAddr@ is the local IP address and @port@ is the local port on which
78-- @ipAddr@ is the local IP address and @port@ is the local port on which
@@ -147,7 +83,18 @@ listenTuplesOnAddr = UF.lmap f listenTuples
147listenOnAddr
83listenOnAddr
148 :: MonadIO m
84 :: MonadIO m
149 => Unfold m ((Word8, Word8, Word8, Word8), PortNumber) Socket
85 => Unfold m ((Word8, Word8, Word8, Word8), PortNumber) Socket
150−listenOnAddr = UF.map fst listenTuplesOnAddr
86+listenOnAddr = UF.lmap f listen
91+ { sockFamily = AF_INET
93+ , sockProto = defaultProtocol -- TCP
94+ , sockOpts = [(NoDelay,1), (ReuseAddr,1)]
96+ , SockAddrInet port (tupleToHostAddress addr)
152-- | Like 'listenOnAddr' but binds on the IPv4 address @0.0.0.0@ i.e. on all
99-- | Like 'listenOnAddr' but binds on the IPv4 address @0.0.0.0@ i.e. on all
153-- IPv4 addresses/interfaces of the machine and listens for TCP connections on
100-- IPv4 addresses/interfaces of the machine and listens for TCP connections on
@@ -175,46 +122,6 @@ listenOnPortLocal = UF.supplyFirst listenOnAddr (127,0,0,1)
176-------------------------------------------------------------------------------
123-------------------------------------------------------------------------------
178−{-# INLINE recvConnectionTuplesWith #-}
179−recvConnectionTuplesWith :: MonadAsync m
180− => Int -> Server -> SerialT m (Socket, SockAddr)
181−recvConnectionTuplesWith tcpListenQ opts = S.unfoldrM step Nothing
184− listener <- liftIO $ initListener tcpListenQ opts
185− r <- liftIO $ accept listener
186− -- XXX error handling
187− return $ Just (r, Just listener)
189− step (Just listener) = do
190− r <- liftIO $ accept listener
191− -- XXX error handling
192− return $ Just (r, Just listener)
194−-- | Start a TCP stream server that listens for connections on the supplied
195−-- server address specification (address family, local interface IP address and
196−-- port). The server generates a stream of connected sockets. The first
197−-- argument is the maximum number of pending connections in the backlog.
200−{-# INLINE connections #-}
201−connections :: MonadAsync m => Int -> Server -> SerialT m Socket
202−connections tcpListenQ opts = fmap fst $
203− recvConnectionTuplesWith tcpListenQ opts
205−{-# INLINE connectionTuplesOnAddr #-}
206−connectionTuplesOnAddr
208− => (Word8, Word8, Word8, Word8)
210− -> SerialT m (Socket, SockAddr)
211−connectionTuplesOnAddr addr port =
212− recvConnectionTuplesWith maxListenQueue Server
213− { serverAddressFamily = AF_INET
214− , serverAddress = SockAddrInet port (tupleToHostAddress addr)
215− , serverSockOpts = [(NoDelay,1), (ReuseAddr,1)]
218-- | Like 'connections' but binds on the specified IPv4 address of the machine
125-- | Like 'connections' but binds on the specified IPv4 address of the machine
219-- and listens for TCP connections on the specified port.
126-- and listens for TCP connections on the specified port.
@@ -222,8 +129,17 @@ connectionTuplesOnAddr addr port =
222{-# INLINE connectionsOnAddr #-}
129{-# INLINE connectionsOnAddr #-}
223connectionsOnAddr
130connectionsOnAddr
224 :: MonadAsync m
131 :: MonadAsync m
225− => (Word8, Word8, Word8, Word8) -> PortNumber -> SerialT m Socket
132+ => (Word8, Word8, Word8, Word8)
226−connectionsOnAddr addr port = fmap fst $ connectionTuplesOnAddr addr port
135+connectionsOnAddr addr port =
136+ connections maxListenQueue SockSpec
137+ { sockFamily = AF_INET
139+ , sockProto = defaultProtocol
140+ , sockOpts = [(NoDelay,1), (ReuseAddr,1)]
142+ (SockAddrInet port (tupleToHostAddress addr))
228-- | Like 'connections' but binds on the IPv4 address @0.0.0.0@ i.e. on all
144-- | Like 'connections' but binds on the IPv4 address @0.0.0.0@ i.e. on all
229-- IPv4 addresses/interfaces of the machine and listens for TCP connections on
145-- IPv4 addresses/interfaces of the machine and listens for TCP connections on