11module Node.Net
2- ( Address
3- , ListenOptions
4- , Server
5- , ServerOptions
6- , address
7- , close
8- , createServer
9- , getConnections
10- , isIP
2+ ( isIP
113 , isIPv4
124 , isIPv6
13- , listen
14- , listenBacklog
15- , listenExclusive
16- , listenHost
17- , listenICP
18- , listenIpv6Only
19- , listenPath
20- , listenPort
21- , listenReadableAll
22- , listenTCP
23- , listenWritableAll
24- , listening
25- , onCloseServer
26- , onConnection
27- , onErrorServer
28- , onListening
29- , serverAllowHalfOpen
30- , serverPauseOnConnect
315 ) where
326
33- import Prelude
34-
35- import Control.Alt ((<|>))
36- import Control.Monad.Except (runExcept )
37- import Data.Either (Either (..), either )
38- import Data.Maybe (Maybe (..))
39- import Data.Nullable (Nullable , toMaybe )
40- import Data.Options (Option , Options , opt , options , (:=))
41- import Effect (Effect )
42- import Effect.Exception (Error )
43- import Effect.Uncurried (EffectFn1 , EffectFn2 , EffectFn3 , mkEffectFn1 , mkEffectFn2 , runEffectFn1 , runEffectFn2 , runEffectFn3 )
44- import Foreign (F , Foreign , readInt , readString )
45- import Foreign.Index (readProp )
46- import Node.Net.Socket (Socket )
47-
48- type Address
49- = { address :: String
50- , family :: String
51- , port :: Int
52- }
53-
54- -- | Options to configure the listening side of a `Server`.
55- -- | These options decide whether the `Server` is ICP or TCP.
56- -- |
57- -- | One of `path` or `port` must be set.
58- -- | Setting `path` will make the `Server` ICP.
59- -- | Setting `port` will make the `Server` TCP.
60- data ListenOptions
61-
62- -- | An ICP or TCP server.
63- foreign import data Server :: Type
64-
65- -- | Options to configure the basics of a `Server`.
66- data ServerOptions
67-
68- foreign import addressImpl :: EffectFn1 Server (Nullable Foreign )
69-
70- -- | Attempts to return the bound address of a `Server`.
71- -- |
72- -- | If the `Server` is not listening, `Nothing` is returned.
73- -- | If the `Server` is ICP, it will return a `String`.
74- -- | If the `Server` is TCP, it will return an `Address`.
75- address :: Server -> Effect (Maybe (Either Address String ))
76- address server = do
77- x <- runEffectFn1 addressImpl server
78- pure (toMaybe x >>= read)
79- where
80- hush :: F ~> Maybe
81- hush f = either (\_ -> Nothing ) Just (runExcept f)
82- read :: Foreign -> Maybe (Either Address String )
83- read value =
84- hush (map Left $ readAddress value)
85- <|> hush (map Right $ readString value)
86- readAddress :: Foreign -> F Address
87- readAddress value = ado
88- address <- readProp " address" value >>= readString
89- family <- readProp " family" value >>= readString
90- port <- readProp " port" value >>= readInt
91- in { address, family, port }
92-
93- foreign import closeImpl :: EffectFn2 Server (EffectFn1 (Nullable Error ) Unit ) Unit
94-
95- -- | Closes the `Server` and invokes the callback after the `'close'` event
96- -- | is emitted.
97- -- | An `Error` is passed to the callback if the `Server` was not open.
98- close :: Server -> (Maybe Error -> Effect Unit ) -> Effect Unit
99- close server callback =
100- runEffectFn2 closeImpl server (mkEffectFn1 \err -> callback $ toMaybe err)
101-
102- foreign import createServerImpl :: EffectFn2 Foreign (EffectFn1 Socket Unit ) Server
103-
104- -- | Creates an ICP or TCP `Server`, returns the `Server`,
105- -- | and adds the callback as a listenter for the `'connection'` event.
106- -- | the `Server` will be ICP or TCP depending on what it `listen`s to.
107- createServer :: Options ServerOptions -> (Socket -> Effect Unit ) -> Effect Server
108- createServer opts callback =
109- runEffectFn2
110- createServerImpl
111- (options opts)
112- (mkEffectFn1 \socket -> callback socket)
113-
114- foreign import getConnectionsImpl :: EffectFn2 Server (EffectFn2 (Nullable Error ) (Nullable Int ) Unit ) Unit
115-
116- -- | Returns the number of concurrent connections to the `Server`.
117- getConnections :: Server -> (Either Error Int -> Effect Unit ) -> Effect Unit
118- getConnections server callback =
119- runEffectFn2 getConnectionsImpl server $ mkEffectFn2 \err' count' ->
120- case toMaybe err', toMaybe count' of
121- Just err, _ -> callback (Left err)
122- _, Just count -> callback (Right count)
123- _, _ -> mempty
124-
1257-- | Returns `4` if the `String` is a valid IPv4 address, `6` if the `String`
1268-- | is a valid IPv6 address, and `0` otherwise.
1279foreign import isIP :: String -> Int
@@ -133,136 +15,3 @@ foreign import isIPv4 :: String -> Boolean
13315-- | Returns `true` if the `String` is a valid IPv4 address,
13416-- | and `false` otherwise.
13517foreign import isIPv6 :: String -> Boolean
136-
137- foreign import listenImpl :: EffectFn3 Server Foreign (Effect Unit ) Unit
138-
139- -- | Starts the `Server` as an ICP or TCP `Server` listening for connections,
140- -- | adds the callback as a listener to the `'listening'` event, and emits the
141- -- | `'listening'` event.
142- listen :: Server -> Options ListenOptions -> Effect Unit -> Effect Unit
143- listen server opts callback =
144- runEffectFn3 listenImpl server (options opts) callback
145-
146- -- | Maximum number of pending connections.
147- -- | Defaults to `511`.
148- listenBacklog :: Option ListenOptions Int
149- listenBacklog = opt " backlog"
150-
151- -- | When `true`, the handle cannot be shared and will result in an error.
152- -- | When `false`, the handle can be shared.
153- -- | Defaults to `false`.
154- listenExclusive :: Option ListenOptions Boolean
155- listenExclusive = opt " exclusive"
156-
157- -- | The host to configure TCP `Server`s.
158- -- |
159- -- | Determines the host the `Server` will attempt to listen on.
160- -- | Defaults to IPv6 `::` if available, and IPv4 `0.0.0.0` otherwise.
161- listenHost :: Option ListenOptions String
162- listenHost = opt " host"
163-
164- -- | Starts the `Server` as an ICP `Server` listening for connections,
165- -- | adds the callback as a listener to the `'listening'` event, and emits the
166- -- | `'listening'` event.
167- listenICP :: Server -> String -> Int -> Effect Unit -> Effect Unit
168- listenICP server path backlog callback =
169- runEffectFn3
170- listenImpl
171- server
172- (options $ listenBacklog := backlog <> listenPath := path)
173- callback
174-
175- -- | When `true`, only binds to IPv6 hosts and not also to IPv4 hosts.
176- -- | Defaults to `false`.
177- listenIpv6Only :: Option ListenOptions Boolean
178- listenIpv6Only = opt " ipv6Only"
179-
180- -- | The path to configure ICP `Server`s.
181- -- |
182- -- | Determines the ICP endpoint the `Server` will attempt to listen on.
183- listenPath :: Option ListenOptions String
184- listenPath = opt " path"
185-
186- -- | The port to configure TCP `Server`s.
187- -- |
188- -- | Determines the TCP endpoint the `Server` will attempt to listen on.
189- -- | When `0`, the OS will assign an arbitrary port.
190- listenPort :: Option ListenOptions Int
191- listenPort = opt " port"
192-
193- -- | Makes the ICP pipe readable for all users.
194- -- | Defaults to `false`.
195- listenReadableAll :: Option ListenOptions Boolean
196- listenReadableAll = opt " readableAll"
197-
198- -- | Starts the `Server` as a TCP `Server` listening for connections,
199- -- | adds the callback as a listener to the `'listening'` event, and emits the
200- -- | `'listening'` event.
201- listenTCP :: Server -> Int -> String -> Int -> Effect Unit -> Effect Unit
202- listenTCP server port host backlog callback =
203- runEffectFn3
204- listenImpl
205- server
206- (options $ listenBacklog := backlog <> listenHost := host <> listenPort := port)
207- callback
208-
209- -- | Makes the ICP pipe writable for all users.
210- -- | Defaults to `false`.
211- listenWritableAll :: Option ListenOptions Boolean
212- listenWritableAll = opt " writableAll"
213-
214- foreign import listeningImpl :: EffectFn1 Server Boolean
215-
216- -- | Returns `true` if the `Server` is listening for connections, and `false`
217- -- | otherwise.
218- listening :: Server -> Effect Boolean
219- listening server = runEffectFn1 listeningImpl server
220-
221- -- | Attaches the callback as a listener to the `'close'` event.
222- -- |
223- -- | `'close'` is emitted when a close occurs.
224- -- | Will not be emitted until all connections have ended.
225- onCloseServer :: Server -> Effect Unit -> Effect Unit
226- onCloseServer server callback =
227- runEffectFn3 onServerImpl " close" server callback
228-
229- -- | Attaches the callback as a listener to the `'connection'` event.
230- -- |
231- -- | `'connection'` is emitted when a new connection is made.
232- onConnection :: Server -> (Socket -> Effect Unit ) -> Effect Unit
233- onConnection server callback =
234- runEffectFn3
235- onServerImpl
236- " connection"
237- server
238- (mkEffectFn1 \socket -> callback socket)
239-
240- -- | Attaches the callback as a listener to the `'error'` event.
241- -- |
242- -- | `'error'` is emitted when an error occurs.
243- onErrorServer :: Server -> (Error -> Effect Unit ) -> Effect Unit
244- onErrorServer server callback =
245- runEffectFn3
246- onServerImpl
247- " error"
248- server
249- (mkEffectFn1 \error -> callback error)
250-
251- -- | Attaches the callback as a listener to the `'listening'` event.
252- -- |
253- -- | `'listening'` is emitted when the `Server` has been bound.
254- onListening :: Server -> Effect Unit -> Effect Unit
255- onListening server callback =
256- runEffectFn3 onServerImpl " listening" server callback
257-
258- foreign import onServerImpl :: forall f . EffectFn3 String Server (f Unit ) Unit
259-
260- -- | Allows half open TCP connections.
261- -- | Defaults to `false`.
262- serverAllowHalfOpen :: Option ServerOptions Boolean
263- serverAllowHalfOpen = opt " allowHalfOpen"
264-
265- -- | When `true`, pauses the `Socket` on incomming connections.
266- -- | Defaults to `false`.
267- serverPauseOnConnect :: Option ServerOptions Boolean
268- serverPauseOnConnect = opt " pauseOnConnect"
0 commit comments