@@ -254,6 +254,37 @@ apiConnect :: LocalEndPoint -- ^ Local end point
254 -> EndPointAddress -- ^ Remote address
254 -> EndPointAddress -- ^ Remote address
255 -> Reliability -- ^ Reliability (ignored)
255 -> Reliability -- ^ Reliability (ignored)
256 -> IO (Either (FailedWith ConnectErrorCode) Connection)
256 -> IO (Either (FailedWith ConnectErrorCode) Connection)
257+-- Special case for self-connection
258+apiConnect ourEndPoint theirAddress _ | ourEndPoint ^. localAddress == theirAddress = do
259+ connAlive <- newMVar True
260+ connId <- modifyMVar (ourEndPoint ^. localState) $ \st -> do
261+ let connId = st ^. nextConnectionId
262+ return (nextConnectionId ^= connId + 1 $ st, connId)
264+ let ourChan :: Chan Event
265+ ourChan = ourEndPoint ^. localChannel
267+ selfSend :: [ByteString] -> IO (Either (FailedWith SendErrorCode) ())
269+ modifyMVar connAlive $ \alive ->
272+ writeChan ourChan (Received connId msg)
273+ return (alive, Right ())
275+ return (alive, Left (FailedWith SendConnectionClosed "Connection closed"))
279+ modifyMVar_ connAlive $ \alive -> do
280+ when alive $ writeChan ourChan (ConnectionClosed connId)
283+ writeChan ourChan (ConnectionOpened connId ReliableOrdered theirAddress)
284+ return . Right $ Connection { send = selfSend
257apiConnect ourEndPoint theirAddress _ = runErrorT $ do
288apiConnect ourEndPoint theirAddress _ = runErrorT $ do
258 theirEndPoint <- findRemoteEndPoint ourEndPoint theirAddress
289 theirEndPoint <- findRemoteEndPoint ourEndPoint theirAddress
259 connId <- requestNewConnection (ourEndPoint, theirEndPoint)
290 connId <- requestNewConnection (ourEndPoint, theirEndPoint)
@@ -325,14 +356,14 @@ findRemoteEndPoint ourEndPoint theirAddress = ErrorT $ go
325 return (connectionTo theirAddress ^= Just (Nothing, theirMVar) $ st, theirMVar)
356 return (connectionTo theirAddress ^= Just (Nothing, theirMVar) $ st, theirMVar)
326 theirState <- readMVar endPoint
357 theirState <- readMVar endPoint
327 case theirState of
358 case theirState of
328− EndPointInvalid err ->
359+ EndPointInvalid err -> do
329 -- We remove the endpoint from the state again because the next call
360 -- We remove the endpoint from the state again because the next call
330 -- to 'connect' might give a different result
361 -- to 'connect' might give a different result
331 modifyMVar state $ \st ->
362 modifyMVar state $ \st ->
332 return (connectionTo theirAddress ^= Nothing $ st, Left err)
363 return (connectionTo theirAddress ^= Nothing $ st, Left err)
333− EndPointValid _ ep ->
364+ EndPointValid _ ep -> do
334 return $ Right ep
365 return $ Right ep
335− EndPointClosed ->
366+ EndPointClosed -> do
338 state :: MVar LocalState
369 state :: MVar LocalState
@@ -348,9 +379,9 @@ connectToRemoteEndPoint ourEndPoint theirMVar theirAddress = do
348 Right (ConnectionRequestEndPointInvalid, sock) -> do
379 Right (ConnectionRequestEndPointInvalid, sock) -> do
349 putMVar theirMVar (EndPointInvalid (invalidAddress "Invalid endpoint"))
380 putMVar theirMVar (EndPointInvalid (invalidAddress "Invalid endpoint"))
350 N.sClose sock
381 N.sClose sock
351− Right (ConnectionRequestCrossed, sock) ->
382+ Right (ConnectionRequestCrossed, sock) -> do
352 N.sClose sock
383 N.sClose sock
353− Left err ->
384+ Left err -> do
354 -- TODO: this isn't quite right; socket *might* have been opened here,
385 -- TODO: this isn't quite right; socket *might* have been opened here,
355 -- in which case we should close it
386 -- in which case we should close it
356 putMVar theirMVar (EndPointInvalid err)
387 putMVar theirMVar (EndPointInvalid err)
@@ -421,12 +452,12 @@ sendRemoteRequest (ourEndPoint, theirEndPoint) header = do
421increaseRemoteRefCount :: Conn -> IO ()
452increaseRemoteRefCount :: Conn -> IO ()
422increaseRemoteRefCount (ourEndPoint, theirEndPoint) = do
453increaseRemoteRefCount (ourEndPoint, theirEndPoint) = do
423 let theirAddr = theirEndPoint ^. remoteAddress
454 let theirAddr = theirEndPoint ^. remoteAddress
424− state = ourEndPoint ^. localState
455+ ourState = ourEndPoint ^. localState
425 -- If this endpoint was closing, cancel that
456 -- If this endpoint was closing, cancel that
426− theirMVar <- modifyMVar state $ \st -> do
457+ theirMVar <- modifyMVar ourState $ \st -> do
427 let Just (isClosing, theirMVar) = st ^. connectionTo theirAddr
458 let Just (isClosing, theirMVar) = st ^. connectionTo theirAddr
428 case isClosing of
459 case isClosing of
429− Nothing ->
460+ Nothing -> do
430 return (st, theirMVar)
461 return (st, theirMVar)
431 Just ep -> do
462 Just ep -> do
432 putMVar theirMVar (EndPointValid 0 ep)
463 putMVar theirMVar (EndPointValid 0 ep)
@@ -475,7 +506,7 @@ handleConnectionRequest transport sock = do
475 mvar <- newEmptyMVar
506 mvar <- newEmptyMVar
476 return (connectionTo theirAddress ^= Just (Nothing, mvar) $ st, (False, mvar))
507 return (connectionTo theirAddress ^= Just (Nothing, mvar) $ st, (False, mvar))
477 Just (_, mvar) ->
508 Just (_, mvar) ->
478− return (st, (ourEndPoint ^. localAddress <= theirAddress, mvar))
509+ return (st, (ourEndPoint ^. localAddress < theirAddress, mvar))
479 if crossed
510 if crossed
481 sendMany sock [encodeInt32 ConnectionRequestCrossed]
512 sendMany sock [encodeInt32 ConnectionRequestCrossed]