git.iko.soy/distributed-process
on master help sign in
Add ConnectHints, reintroduce SendClosed
393c37cEdsko de Vries
network-transport/network-transport.cabal+4−4
@@ -23,7 +23,7 @@ Library
23 Network.Transport.Chan,
23 Network.Transport.Chan,
24 Network.Transport.TCP,
24 Network.Transport.TCP,
25 Network.Transport.Util
25 Network.Transport.Util
26− extensions: OverloadedStrings, ForeignFunctionInterface, DeriveDataTypeable
26+ extensions: OverloadedStrings, ForeignFunctionInterface, DeriveDataTypeable, EmptyDataDecls
27 ghc-options: -Wall -fno-warn-unused-do-bind
27 ghc-options: -Wall -fno-warn-unused-do-bind
28 HS-Source-Dirs: src
28 HS-Source-Dirs: src
29
29
@@ -38,7 +38,7 @@ Test-Suite TestTCP
38 mtl,
38 mtl,
39 transformers,
39 transformers,
40 ansi-terminal
40 ansi-terminal
41− extensions: OverloadedStrings, ForeignFunctionInterface, DeriveDataTypeable, ExistentialQuantification, FlexibleInstances, RankNTypes, OverlappingInstances
41+ extensions: OverloadedStrings, ForeignFunctionInterface, DeriveDataTypeable, EmptyDataDecls, ExistentialQuantification, FlexibleInstances, RankNTypes, OverlappingInstances
42 ghc-options: -Wall -fno-warn-unused-do-bind
42 ghc-options: -Wall -fno-warn-unused-do-bind
43 HS-Source-Dirs: tests src
43 HS-Source-Dirs: tests src
44
44
@@ -52,7 +52,7 @@ Test-Suite TestMulticastInMemory
52 mtl,
52 mtl,
53 transformers,
53 transformers,
54 ansi-terminal
54 ansi-terminal
55− extensions: OverloadedStrings, ForeignFunctionInterface, DeriveDataTypeable, ExistentialQuantification, FlexibleInstances, RankNTypes, OverlappingInstances
55+ extensions: OverloadedStrings, ForeignFunctionInterface, DeriveDataTypeable, EmptyDataDecls, ExistentialQuantification, FlexibleInstances, RankNTypes, OverlappingInstances
56 ghc-options: -Wall -fno-warn-unused-do-bind
56 ghc-options: -Wall -fno-warn-unused-do-bind
57 HS-Source-Dirs: tests src
57 HS-Source-Dirs: tests src
58
58
@@ -66,6 +66,6 @@ Test-Suite TestInMemory
66 mtl,
66 mtl,
67 transformers,
67 transformers,
68 ansi-terminal
68 ansi-terminal
69− extensions: OverloadedStrings, ForeignFunctionInterface, DeriveDataTypeable, ExistentialQuantification, FlexibleInstances, RankNTypes, OverlappingInstances
69+ extensions: OverloadedStrings, ForeignFunctionInterface, DeriveDataTypeable, EmptyDataDecls, ExistentialQuantification, FlexibleInstances, RankNTypes, OverlappingInstances
70 ghc-options: -Wall -fno-warn-unused-do-bind
70 ghc-options: -Wall -fno-warn-unused-do-bind
71 HS-Source-Dirs: tests src
71 HS-Source-Dirs: tests src
network-transport/src/Network/Transport.hs+28−15
@@ -9,6 +9,9 @@ module Network.Transport ( -- * Types
9 , MulticastGroup(..)
9 , MulticastGroup(..)
10 , EndPointAddress(..)
10 , EndPointAddress(..)
11 , MulticastAddress(..)
11 , MulticastAddress(..)
12+ -- * Hints
13+ , ConnectHints
14+ , defaultConnectHints
12 -- * Error codes
15 -- * Error codes
13 , TransportError(..)
16 , TransportError(..)
14 , NewEndPointErrorCode(..)
17 , NewEndPointErrorCode(..)
@@ -43,7 +46,7 @@ data EndPoint = EndPoint {
43 -- | EndPointAddress of the endpoint.
46 -- | EndPointAddress of the endpoint.
44 , address :: EndPointAddress
47 , address :: EndPointAddress
45 -- | Create a new lightweight connection.
48 -- | Create a new lightweight connection.
46− , connect :: EndPointAddress -> Reliability -> IO (Either (TransportError ConnectErrorCode) Connection)
49+ , connect :: EndPointAddress -> Reliability -> ConnectHints -> IO (Either (TransportError ConnectErrorCode) Connection)
47 -- | Create a new multicast group.
50 -- | Create a new multicast group.
48 , newMulticastGroup :: IO (Either (TransportError NewMulticastGroupErrorCode) MulticastGroup)
51 , newMulticastGroup :: IO (Either (TransportError NewMulticastGroupErrorCode) MulticastGroup)
49 -- | Resolve an address to a multicast group.
52 -- | Resolve an address to a multicast group.
@@ -76,7 +79,7 @@ data Event =
76 | ErrorEvent (TransportError EventErrorCode)
79 | ErrorEvent (TransportError EventErrorCode)
77 deriving Show
80 deriving Show
78
81
79−-- | Connection IDs enable receivers to distinguish one connection from another.
82+-- | Connection data ConnectHintsIDs enable receivers to distinguish one connection from another.
80type ConnectionId = Int
83type ConnectionId = Int
81
84
82-- | Reliability guarantees of a connection.
85-- | Reliability guarantees of a connection.
@@ -118,10 +121,31 @@ newtype MulticastAddress = MulticastAddress { multicastAddressToByteString :: By
118instance Show MulticastAddress where
121instance Show MulticastAddress where
119 show = show . multicastAddressToByteString
122 show = show . multicastAddressToByteString
120
123
124+--------------------------------------------------------------------------------
125+-- Hints --
126+-- --
127+-- Hints provide transport-generic "suggestions". For now, these are --
128+-- placeholders only. --
129+--------------------------------------------------------------------------------
130+
131+-- Hints used by 'connect'
132+data ConnectHints
133+
134+-- Default hints for connecting
135+defaultConnectHints :: ConnectHints
136+defaultConnectHints = undefined
137+
121--------------------------------------------------------------------------------
138--------------------------------------------------------------------------------
122-- Error codes --
139-- Error codes --
140+-- --
141+-- Errors should be transport-implementation independent. The deciding factor --
142+-- for distinguishing one kind of error from another should be: might --
143+-- application code have to take a different action depending on the kind of --
144+-- error? --
123--------------------------------------------------------------------------------
145--------------------------------------------------------------------------------
124
146
147+-- | Errors returned by Network.Transport API functions consist of an error
148+-- code and a human readable description of the problem
125data TransportError error = TransportError error String
149data TransportError error = TransportError error String
126 deriving (Show, Typeable)
150 deriving (Show, Typeable)
127
151
@@ -133,33 +157,26 @@ instance (Typeable err, Show err) => Exception (TransportError err)
133-- | Errors during the creation of an endpoint
157-- | Errors during the creation of an endpoint
134data NewEndPointErrorCode =
158data NewEndPointErrorCode =
135 -- | Not enough resources
159 -- | Not enough resources
136− -- (i.e., this could be a temporary local problem)
137 NewEndPointInsufficientResources
160 NewEndPointInsufficientResources
138 -- | Failed for some other reason
161 -- | Failed for some other reason
139− -- (i.e., there is probably no point trying again)
140 | NewEndPointFailed
162 | NewEndPointFailed
141 deriving (Show, Typeable)
163 deriving (Show, Typeable)
142
164
143-- | Connection failure
165-- | Connection failure
144data ConnectErrorCode =
166data ConnectErrorCode =
145 -- | Could not resolve the address
167 -- | Could not resolve the address
146− -- (i.e., this could be a temporary remote problem)
147 ConnectNotFound
168 ConnectNotFound
148 -- | Insufficient resources (for instance, no more sockets available)
169 -- | Insufficient resources (for instance, no more sockets available)
149− -- (i.e., this could be a temporary local problem)
150 | ConnectInsufficientResources
170 | ConnectInsufficientResources
151 -- | Failed for other reasons (including syntax error)
171 -- | Failed for other reasons (including syntax error)
152− -- (i.e., there is probably no point trying again).
153 | ConnectFailed
172 | ConnectFailed
154 deriving (Show, Typeable)
173 deriving (Show, Typeable)
155
174
156-- | Failure during the creation of a new multicast group
175-- | Failure during the creation of a new multicast group
157data NewMulticastGroupErrorCode =
176data NewMulticastGroupErrorCode =
158 -- | Insufficient resources
177 -- | Insufficient resources
159− -- (i.e., this could be a temporary problem)
160 NewMulticastGroupInsufficientResources
178 NewMulticastGroupInsufficientResources
161 -- | Failed for some other reason
179 -- | Failed for some other reason
162− -- (i.e., there is probably no point trying again)
163 | NewMulticastGroupFailed
180 | NewMulticastGroupFailed
164 -- | Not all transport implementations support multicast
181 -- | Not all transport implementations support multicast
165 | NewMulticastGroupUnsupported
182 | NewMulticastGroupUnsupported
@@ -168,10 +185,8 @@ data NewMulticastGroupErrorCode =
168-- | Failure during the resolution of a multicast group
185-- | Failure during the resolution of a multicast group
169data ResolveMulticastGroupErrorCode =
186data ResolveMulticastGroupErrorCode =
170 -- | Multicast group not found
187 -- | Multicast group not found
171− -- (i.e., this could be a temporary problem)
172 ResolveMulticastGroupNotFound
188 ResolveMulticastGroupNotFound
173 -- | Failed for some other reason (including syntax error)
189 -- | Failed for some other reason (including syntax error)
174− -- (i.e., there is probably no point trying again)
175 | ResolveMulticastGroupFailed
190 | ResolveMulticastGroupFailed
176 -- | Not all transport implementations support multicast
191 -- | Not all transport implementations support multicast
177 | ResolveMulticastGroupUnsupported
192 | ResolveMulticastGroupUnsupported
@@ -179,11 +194,9 @@ data ResolveMulticastGroupErrorCode =
179
194
180-- | Failure during sending a message
195-- | Failure during sending a message
181data SendErrorCode =
196data SendErrorCode =
182− -- | Could not send this message
197+ -- | Connection was closed
183− -- (but another attempt might succeed)
198+ SendClosed
184− SendUnreachable
185 -- | Send failed for some other reason
199 -- | Send failed for some other reason
186− -- (and retrying probably won't help)
187 | SendFailed
200 | SendFailed
188 deriving (Show, Typeable)
201 deriving (Show, Typeable)
189
202
network-transport/src/Network/Transport/Chan.hs+10−5
@@ -53,8 +53,13 @@ apiNewEndPoint state = do
53 }
53 }
54
54
55-- | Create a new connection
55-- | Create a new connection
56+apiConnect :: EndPointAddress
57+ -> MVar TransportState
58+ -> EndPointAddress
59+ -> Reliability
60+ -> ConnectHints
56−apiConnect :: EndPointAddress -> MVar TransportState -> EndPointAddress -> Reliability -> IO (Either (TransportError ConnectErrorCode) Connection)
61+ -> IO (Either (TransportError ConnectErrorCode) Connection)
57−apiConnect myAddress state theirAddress _ = do
62+apiConnect myAddress state theirAddress _reliability _hints = do
58 (chan, conn) <- modifyMVar state $ \st -> do
63 (chan, conn) <- modifyMVar state $ \st -> do
59 let chan = st ^. channelAt theirAddress
64 let chan = st ^. channelAt theirAddress
60 let conn = st ^. nextConnectionIdAt theirAddress
65 let conn = st ^. nextConnectionIdAt theirAddress
@@ -105,10 +110,10 @@ createMulticastGroup state ourAddress groupAddress group =
105 cs <- (^. channels) <$> readMVar state
110 cs <- (^. channels) <$> readMVar state
106 es <- readMVar group
111 es <- readMVar group
107 forM_ (Set.elems es) $ \ep -> do
112 forM_ (Set.elems es) $ \ep -> do
108− let ch = (cs ^. at ep "Invalid endpoint")
113+ let ch = cs ^. at ep "Invalid endpoint"
109 writeChan ch (ReceivedMulticast groupAddress payload)
114 writeChan ch (ReceivedMulticast groupAddress payload)
110− , multicastSubscribe = modifyMVar_ group $ return . (Set.insert ourAddress)
115+ , multicastSubscribe = modifyMVar_ group $ return . Set.insert ourAddress
111− , multicastUnsubscribe = modifyMVar_ group $ return . (Set.delete ourAddress)
116+ , multicastUnsubscribe = modifyMVar_ group $ return . Set.delete ourAddress
112 , multicastClose = return ()
117 , multicastClose = return ()
113 }
118 }
114
119
network-transport/src/Network/Transport/TCP.hs+7−8
@@ -370,10 +370,11 @@ apiNewEndPoint transport = try $ do
370apiConnect :: LocalEndPoint -- ^ Local end point
370apiConnect :: LocalEndPoint -- ^ Local end point
371 -> EndPointAddress -- ^ Remote address
371 -> EndPointAddress -- ^ Remote address
372 -> Reliability -- ^ Reliability (ignored)
372 -> Reliability -- ^ Reliability (ignored)
373+ -> ConnectHints -- ^ Hints (ignored for now)
373 -> IO (Either (TransportError ConnectErrorCode) Connection)
374 -> IO (Either (TransportError ConnectErrorCode) Connection)
374−apiConnect ourEndPoint theirAddress _ | localAddress ourEndPoint == theirAddress =
375+apiConnect ourEndPoint theirAddress _reliability _hints | localAddress ourEndPoint == theirAddress =
375 connectToSelf ourEndPoint
376 connectToSelf ourEndPoint
376−apiConnect ourEndPoint theirAddress _ = try $ do
377+apiConnect ourEndPoint theirAddress _reliability _hints = try $ do
377 (theirEndPoint, connId) <- requestConnectionTo ourEndPoint theirAddress
378 (theirEndPoint, connId) <- requestConnectionTo ourEndPoint theirAddress
378 -- connAlive can be an IORef rather than an MVar because it is protected by
379 -- connAlive can be an IORef rather than an MVar because it is protected by
379 -- the remoteState MVar. We don't need the overhead of locking twice.
380 -- the remoteState MVar. We don't need the overhead of locking twice.
@@ -422,9 +423,9 @@ apiSend theirEndPoint connId connAlive payload = do
422 alive <- readIORef connAlive
423 alive <- readIORef connAlive
423 try $ if alive
424 try $ if alive
424 then mapExceptionIO sendFailed $ sendOn vst (encodeInt32 connId : prependLength payload)
425 then mapExceptionIO sendFailed $ sendOn vst (encodeInt32 connId : prependLength payload)
425− else throw $ TransportError SendFailed "Connection closed"
426+ else throw $ TransportError SendClosed "Connection closed"
426 RemoteEndPointClosed -> do
427 RemoteEndPointClosed -> do
427− return (Left $ TransportError SendFailed "Connection closed")
428+ return (Left $ TransportError SendClosed "Connection lost")
428 RemoteEndPointClosing _ _ ->
429 RemoteEndPointClosing _ _ ->
429 -- The only way for the endpoint to be in closing state, while a
430 -- The only way for the endpoint to be in closing state, while a
430 -- connection is still active, is for the application to call 'close'
431 -- connection is still active, is for the application to call 'close'
@@ -433,7 +434,7 @@ apiSend theirEndPoint connId connAlive payload = do
433 -- yet. Even if the remote endpoint comes back with "please don't
434 -- yet. Even if the remote endpoint comes back with "please don't
434 -- close", this still means that our *outgoing* connection has been
435 -- close", this still means that our *outgoing* connection has been
435 -- closed
436 -- closed
436− return (Left $ TransportError SendFailed "Connection closed")
437+ return (Left $ TransportError SendClosed "Connection lost")
437 RemoteEndPointInvalid _ ->
438 RemoteEndPointInvalid _ ->
438 error "apiSend RELY violation"
439 error "apiSend RELY violation"
439 where
440 where
@@ -706,9 +707,7 @@ socketToEndPoint (EndPointAddress ourAddress) theirAddress = try $ do
706 where
707 where
707 createSocket :: N.AddrInfo -> IO N.Socket
708 createSocket :: N.AddrInfo -> IO N.Socket
708 createSocket addr = mapExceptionIO insufficientResources $ do
709 createSocket addr = mapExceptionIO insufficientResources $ do
709− sock <- N.socket (N.addrFamily addr) N.Stream N.defaultProtocol
710+ N.socket (N.addrFamily addr) N.Stream N.defaultProtocol
710− -- putStrLn $ "Created client socket " ++ show sock
711− return sock
712
711
713 invalidAddress, insufficientResources, failed :: IOException -> TransportError ConnectErrorCode
712 invalidAddress, insufficientResources, failed :: IOException -> TransportError ConnectErrorCode
714 invalidAddress = TransportError ConnectNotFound . show
713 invalidAddress = TransportError ConnectNotFound . show
network-transport/tests/TestTCP.hs+9−9
@@ -77,7 +77,7 @@ testEarlyDisconnect nextPort = do
77 -- establish a connection to them. This should re-establish the broken
77 -- establish a connection to them. This should re-establish the broken
78 -- TCP connection.
78 -- TCP connection.
79 tlog "Trying to connect to client"
79 tlog "Trying to connect to client"
80− Right conn <- connect endpoint theirAddr ReliableOrdered
80+ Right conn <- connect endpoint theirAddr ReliableOrdered defaultConnectHints
81
81
82 -- TEST 3: To test the connection, we do a simple ping test; as before,
82 -- TEST 3: To test the connection, we do a simple ping test; as before,
83 -- however, the remote client won't close the connection nicely but just
83 -- however, the remote client won't close the connection nicely but just
@@ -97,7 +97,7 @@ testEarlyDisconnect nextPort = do
97 return ()
97 return ()
98
98
99 -- TEST 4: A subsequent send on an already-open connection will now break
99 -- TEST 4: A subsequent send on an already-open connection will now break
100− Left (TransportError SendFailed _) <- send conn ["ping2"]
100+ Left (TransportError SendClosed _) <- send conn ["ping2"]
101
101
102 -- *Pfew*
102 -- *Pfew*
103 putMVar serverDone ()
103 putMVar serverDone ()
@@ -183,7 +183,7 @@ testEarlyCloseSocket nextPort = do
183 -- establish a connection to them. This should re-establish the broken
183 -- establish a connection to them. This should re-establish the broken
184 -- TCP connection.
184 -- TCP connection.
185 tlog "Trying to connect to client"
185 tlog "Trying to connect to client"
186− Right conn <- connect endpoint theirAddr ReliableOrdered
186+ Right conn <- connect endpoint theirAddr ReliableOrdered defaultConnectHints
187
187
188 -- TEST 3: To test the connection, we do a simple ping test; as before,
188 -- TEST 3: To test the connection, we do a simple ping test; as before,
189 -- however, the remote client won't close the connection nicely but just
189 -- however, the remote client won't close the connection nicely but just
@@ -208,7 +208,7 @@ testEarlyCloseSocket nextPort = do
208 return ()
208 return ()
209
209
210 -- TEST 4: A subsequent send on an already-open connection will now break
210 -- TEST 4: A subsequent send on an already-open connection will now break
211− Left (TransportError SendFailed _) <- send conn ["ping2"]
211+ Left (TransportError SendClosed _) <- send conn ["ping2"]
212
212
213 -- *Pfew*
213 -- *Pfew*
214 putMVar serverDone ()
214 putMVar serverDone ()
@@ -275,19 +275,19 @@ testInvalidConnect nextPort = do
275
275
276 -- Syntax error in the endpoint address
276 -- Syntax error in the endpoint address
277 Left (TransportError ConnectFailed _) <-
277 Left (TransportError ConnectFailed _) <-
278− connect endpoint (EndPointAddress "InvalidAddress") ReliableOrdered
278+ connect endpoint (EndPointAddress "InvalidAddress") ReliableOrdered defaultConnectHints
279
279
280 -- Syntax connect, but invalid hostname (TCP address lookup failure)
280 -- Syntax connect, but invalid hostname (TCP address lookup failure)
281 Left (TransportError ConnectNotFound _) <-
281 Left (TransportError ConnectNotFound _) <-
282− connect endpoint (encodeEndPointAddress "invalidHost" "port" 0) ReliableOrdered
282+ connect endpoint (encodeEndPointAddress "invalidHost" "port" 0) ReliableOrdered defaultConnectHints
283
283
284 -- TCP address correct, but nobody home at that address
284 -- TCP address correct, but nobody home at that address
285 Left (TransportError ConnectNotFound _) <-
285 Left (TransportError ConnectNotFound _) <-
286− connect endpoint (encodeEndPointAddress "127.0.0.1" "9000" 0) ReliableOrdered
286+ connect endpoint (encodeEndPointAddress "127.0.0.1" "9000" 0) ReliableOrdered defaultConnectHints
287
287
288 -- Valid TCP address but invalid endpoint number
288 -- Valid TCP address but invalid endpoint number
289 Left (TransportError ConnectNotFound _) <-
289 Left (TransportError ConnectNotFound _) <-
290− connect endpoint (encodeEndPointAddress "127.0.0.1" port 1) ReliableOrdered
290+ connect endpoint (encodeEndPointAddress "127.0.0.1" port 1) ReliableOrdered defaultConnectHints
291
291
292 return ()
292 return ()
293
293
@@ -404,7 +404,7 @@ testBlockAfterCloseSocket nextPort = do
404 -- At this point the server will have sent a CloseSocket request to the
404 -- At this point the server will have sent a CloseSocket request to the
405 -- client, and must block until the client responds
405 -- client, and must block until the client responds
406 tlog "Server waiting to connect to the client.."
406 tlog "Server waiting to connect to the client.."
407− Right _ <- readMVar clientAddr >>= \addr -> connect endpoint addr ReliableOrdered
407+ Right _ <- readMVar clientAddr >>= \addr -> connect endpoint addr ReliableOrdered defaultConnectHints
408
408
409 tlog "Server waiting.."
409 tlog "Server waiting.."
410
410
network-transport/tests/TestTransport.hs+10−5
@@ -6,7 +6,8 @@ import TestAuxiliary (forkTry, runTests)
6import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar, readMVar)
6import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar, readMVar)
7import Control.Monad (replicateM, replicateM_, when, guard, forM_)
7import Control.Monad (replicateM, replicateM_, when, guard, forM_)
8import Control.Monad.Error ()
8import Control.Monad.Error ()
9−import Network.Transport
9+import Network.Transport hiding (connect)
10+import qualified Network.Transport as NT
10import Network.Transport.Internal (tlog)
11import Network.Transport.Internal (tlog)
11import Network.Transport.Util (spawn)
12import Network.Transport.Util (spawn)
12import Data.ByteString (ByteString)
13import Data.ByteString (ByteString)
@@ -16,6 +17,10 @@ import qualified Data.Map as Map (empty, insert, delete, findWithDefault, adjust
16import Data.String (fromString)
17import Data.String (fromString)
17import Traced
18import Traced
18
19
20+-- | We overload connect to always pass the default hints
21+connect :: EndPoint -> EndPointAddress -> Reliability -> IO (Either (TransportError ConnectErrorCode) Connection)
22+connect ep addr rel = NT.connect ep addr rel defaultConnectHints
23+
19-- | Server that echoes messages straight back to the origin endpoint.
24-- | Server that echoes messages straight back to the origin endpoint.
20echoServer :: EndPoint -> IO ()
25echoServer :: EndPoint -> IO ()
21echoServer endpoint = do
26echoServer endpoint = do
@@ -390,12 +395,12 @@ testSendAfterClose transport numRepeats = do
390 -- connection (i.e., on a closed connection while there is still another
395 -- connection (i.e., on a closed connection while there is still another
391 -- connection open)
396 -- connection open)
392 close conn2
397 close conn2
393− Left (TransportError SendFailed _) <- send conn2 ["ping2"]
398+ Left (TransportError SendClosed _) <- send conn2 ["ping2"]
394
399
395 -- Now close the first connection, and output on it (i.e., output while
400 -- Now close the first connection, and output on it (i.e., output while
396 -- there are no lightweight connection at all anymore)
401 -- there are no lightweight connection at all anymore)
397 close conn1
402 close conn1
398− Left (TransportError SendFailed _) <- send conn2 ["ping2"]
403+ Left (TransportError SendClosed _) <- send conn2 ["ping2"]
399
404
400 return ()
405 return ()
401
406
@@ -558,7 +563,7 @@ testCloseEndPoint transport _ = do
558 ConnectionClosed cid'' <- receive endpoint ; True <- return $ cid == cid''
563 ConnectionClosed cid'' <- receive endpoint ; True <- return $ cid == cid''
559 ErrorEvent (TransportError (EventConnectionLost addr' []) _) <- receive endpoint ; True <- return $ addr' == theirAddr
564 ErrorEvent (TransportError (EventConnectionLost addr' []) _) <- receive endpoint ; True <- return $ addr' == theirAddr
560
565
561− Left (TransportError SendFailed _) <- send conn ["pong2"]
566+ Left (TransportError SendClosed _) <- send conn ["pong2"]
562
567
563 return ()
568 return ()
564
569
@@ -596,7 +601,7 @@ testCloseEndPoint transport _ = do
596 EndPointClosed <- receive endpoint
601 EndPointClosed <- receive endpoint
597
602
598 -- Attempt to send should fail with connection closed
603 -- Attempt to send should fail with connection closed
599− Left (TransportError SendFailed _) <- send conn ["ping2"]
604+ Left (TransportError SendClosed _) <- send conn ["ping2"]
600
605
601 -- An attempt to close the already closed connection should just return
606 -- An attempt to close the already closed connection should just return
602 () <- close conn
607 () <- close conn