git.iko.soy/distributed-process
on master help sign in
Deal with stray ConnectionRequestCrossed messages
commit08ac22b316569fe8930cfb5d4fc3da7b556f4b7e authorEdsko de Vries <edsko@edsko.net> dateWed 30 May 2012, 12:00 (14 years ago) parent87b8a75
1 file changed+28−23
network-transport/src/Network/Transport/TCP.hs+28−23
network-transport/src/Network/Transport/TCP.hs+28−23
@@ -733,7 +733,7 @@ requestConnectionTo :: LocalEndPoint
733733requestConnectionTo ourEndPoint theirAddress = go
734734 where
735735 go = do
736− (theirEndPoint, isNew, _) <- mapIOException connectFailed $
736+ (theirEndPoint, isNew) <- mapIOException connectFailed $
737737 findRemoteEndPoint ourEndPoint theirAddress Local
738738
739739 if isNew
@@ -774,6 +774,7 @@ setupRemoteEndPoint (ourEndPoint, theirEndPoint) = do
774774 Right (sock, ConnectionRequestCrossed) -> do
775775 -- We leave the endpoint in Init state, handleConnectionRequest will
776776 -- take care of it
777+ resolveInit (ourEndPoint, theirEndPoint) (RemoteEndPointClosed Nothing)
777778 tryCloseSocket sock
778779 return False
779780 Left err -> do
@@ -812,22 +813,22 @@ setupRemoteEndPoint (ourEndPoint, theirEndPoint) = do
812813 theirState = remoteState theirEndPoint
813814 invalidAddress = TransportError ConnectNotFound
814815
815−-- TODO: Document
816−-- TODO: is this what we want? modifyRemoteState only does something special
817−-- when an exception is thrown in the Valid case.
816+-- | Resolve an endpoint currently in 'Init' state
818817resolveInit :: EndPointPair -> RemoteState -> IO ()
819818resolveInit (ourEndPoint, theirEndPoint) newState =
820− modifyRemoteState_ (ourEndPoint, theirEndPoint) $ remoteStateIdentity
821− { caseInit = \resolved _ -> do
822− putMVar resolved ()
823− return newState
824− , caseInvalid = \_ -> throwException
825− , caseValid = \_ -> throwException
826− , caseClosing = \_ _ -> throwException
827− , caseClosed = \_ -> throwException
828− }
829− where
830− throwException = throwIO $ userError "resolveInit: not in Init state"
819+ modifyMVar_ (remoteState theirEndPoint) $ \st -> case st of
820+ RemoteEndPointInit resolved _ -> do
821+ putMVar resolved ()
822+ case newState of
823+ RemoteEndPointClosed _ ->
824+ removeRemoteEndPoint (ourEndPoint, theirEndPoint)
825+ _ ->
826+ return ()
827+ return newState
828+ RemoteEndPointClosed (Just ex) ->
829+ throwIO ex
830+ _ ->
831+ relyViolation (ourEndPoint, theirEndPoint) "resolveInit"
831832
832833-- | Establish a connection to a remote endpoint
833834socketToEndPoint :: EndPointAddress -- ^ Our address
@@ -1157,10 +1158,10 @@ handleConnectionRequest transport sock = handle handleException $ do
11571158 go :: LocalEndPoint -> EndPointAddress -> IO ()
11581159 go ourEndPoint theirAddress = do
11591160 mEndPoint <- handle ((>> return Nothing) . invalidEndPoint) $ do
1160− (theirEndPoint, _, crossed) <-
1161+ (theirEndPoint, isNew) <-
11611162 findRemoteEndPoint ourEndPoint theirAddress Remote
11621163
1163− if crossed
1164+ if not isNew
11641165 then do
11651166 tryIO $ sendMany sock [encodeInt32 ConnectionRequestCrossed]
11661167 tryCloseSocket sock
@@ -1193,13 +1194,12 @@ handleConnectionRequest transport sock = handle handleException $ do
11931194 tryCloseSocket sock
11941195
11951196-- | Find a remote endpoint. If the remote endpoint does not yet exist we
1196−-- create it in Init state. Returns if the endpoint was new and, for requests
1197−-- of Remote origin, whether the request crossed.
1197+-- create it in Init state. Returns if the endpoint was new.
11981198findRemoteEndPoint
11991199 :: LocalEndPoint
12001200 -> EndPointAddress
12011201 -> Origin
1202− -> IO (RemoteEndPoint, Bool, Bool)
1202+ -> IO (RemoteEndPoint, Bool)
12031203findRemoteEndPoint ourEndPoint theirAddress findOrigin = go
12041204 where
12051205 go = do
@@ -1226,7 +1226,7 @@ findRemoteEndPoint ourEndPoint theirAddress findOrigin = go
12261226
12271227 if isNew
12281228 then
1229− return (theirEndPoint, True, False)
1229+ return (theirEndPoint, True)
12301230 else do
12311231 let theirState = remoteState theirEndPoint
12321232 snapshot <- modifyMVar theirState $ \st -> case st of
@@ -1251,14 +1251,19 @@ findRemoteEndPoint ourEndPoint theirAddress findOrigin = go
12511251 case (findOrigin, initOrigin) of
12521252 (Local, Local) -> readMVar resolved >> go
12531253 (Local, Remote) -> readMVar resolved >> go
1254− (Remote, Local) -> return (theirEndPoint, False, ourAddress < theirAddress)
1254+ (Remote, Local) -> if ourAddress > theirAddress
1255+ then
1256+ -- Wait for the Crossed message
1257+ readMVar resolved >> go
1258+ else
1259+ return (theirEndPoint, False)
12551260 (Remote, Remote) -> throwIO $ userError "Already connected (B)"
12561261 RemoteEndPointValid _ ->
12571262 -- We assume that the request crossed if we find the endpoint in
12581263 -- Valid state. It is possible that this is really an invalid
12591264 -- request, but only in the case of a broken client (we don't
12601265 -- maintain enough history to be able to tell the difference).
1261− return (theirEndPoint, False, True)
1266+ return (theirEndPoint, False)
12621267 RemoteEndPointClosing resolved _ ->
12631268 readMVar resolved >> go
12641269 RemoteEndPointClosed Nothing ->