@@ -80,7 +80,7 @@ import Control.Monad.Error (ErrorT(..), runErrorT)
80import Control.Exception ( IOException
80import Control.Exception ( IOException
81 , SomeException
81 , SomeException
85 , bracketOnError
85 , bracketOnError
@@ -475,6 +475,10 @@ apiClose (ourEndPoint, theirEndPoint) connId connAlive = void . tryIO $ do
475-- GUARANTEE: The state of the remote endpoint will not be changed.
475-- GUARANTEE: The state of the remote endpoint will not be changed.
476apiSend :: EndPointPair -> ConnectionId -> IORef Bool -> [ByteString] -> IO (Either (TransportError SendErrorCode) ())
476apiSend :: EndPointPair -> ConnectionId -> IORef Bool -> [ByteString] -> IO (Either (TransportError SendErrorCode) ())
477apiSend (ourEndPoint, theirEndPoint) connId connAlive payload =
477apiSend (ourEndPoint, theirEndPoint) connId connAlive payload =
478+ -- The 'join' joins the inner exception that we explicitly return) for
479+ -- instance if the connection is closed) with the outer exception (which is
480+ -- returned by 'try' when an exception is thrown by 'sendOn', and handled
481+ -- by 'withRemoteState')
478 join <$> (try . mapExceptionIO sendFailed $ withRemoteState (ourEndPoint, theirEndPoint)
482 join <$> (try . mapExceptionIO sendFailed $ withRemoteState (ourEndPoint, theirEndPoint)
479 -- RemoteEndPointInvalid
483 -- RemoteEndPointInvalid
480 (\_ -> fail "apiSend RELY violation")
484 (\_ -> fail "apiSend RELY violation")
@@ -636,7 +640,7 @@ createLocalEndPoint transport = do
637 return (TransportValid . (localEndPointAt addr ^= Just localEndPoint) . (nextEndPointId ^= ix + 1) $ vst, localEndPoint)
641 return (TransportValid . (localEndPointAt addr ^= Just localEndPoint) . (nextEndPointId ^= ix + 1) $ vst, localEndPoint)
638 TransportClosed ->
642 TransportClosed ->
639− throw (TransportError NewEndPointFailed "Transport closed")
643+ throwIO (TransportError NewEndPointFailed "Transport closed")
641-- | Request a connection to a remote endpoint
645-- | Request a connection to a remote endpoint
@@ -676,7 +680,7 @@ requestConnectionTo ourEndPoint theirAddress = go
676 -- won't matter.
680 -- won't matter.
677 case endPointStateSnapshot of
681 case endPointStateSnapshot of
678 RemoteEndPointInvalid err ->
682 RemoteEndPointInvalid err ->
679− throw err
683+ throwIO err
681 RemoteEndPointClosing resolved _ ->
685 RemoteEndPointClosing resolved _ ->
682 -- If the remote endpoint is closing, then we need to block until
686 -- If the remote endpoint is closing, then we need to block until
@@ -700,7 +704,7 @@ requestConnectionTo ourEndPoint theirAddress = go
700 reply <- mapExceptionIO connectFailed $ doRemoteRequest (ourEndPoint, theirEndPoint) RequestConnectionId
704 reply <- mapExceptionIO connectFailed $ doRemoteRequest (ourEndPoint, theirEndPoint) RequestConnectionId
701 case decodeInt32 . BS.concat $ reply of
705 case decodeInt32 . BS.concat $ reply of
702 Nothing ->
706 Nothing ->
703− throw (connectFailed $ userError "Invalid integer")
707+ throwIO (connectFailed $ userError "Invalid integer")
704 Just cid ->
708 Just cid ->
705 return (theirEndPoint, cid)
709 return (theirEndPoint, cid)
@@ -712,7 +716,7 @@ requestConnectionTo ourEndPoint theirAddress = go
712 findTheirEndPoint = do
716 findTheirEndPoint = do
713 (theirEndPoint, isNew) <- modifyMVar ourState $ \st -> case st of
717 (theirEndPoint, isNew) <- modifyMVar ourState $ \st -> case st of
714 LocalEndPointClosed ->
718 LocalEndPointClosed ->
715− throw (TransportError ConnectFailed "Local endpoint closed")
719+ throwIO (TransportError ConnectFailed "Local endpoint closed")
716 LocalEndPointValid vst ->
720 LocalEndPointValid vst ->
717 case vst ^. localConnectionTo theirAddress of
721 case vst ^. localConnectionTo theirAddress of
718 Just theirEndPoint ->
722 Just theirEndPoint ->
@@ -809,7 +813,7 @@ socketToEndPoint :: EndPointAddress -- ^ Our address
809 -> IO (Either (TransportError ConnectErrorCode) (N.Socket, ConnectionRequestResponse))
813 -> IO (Either (TransportError ConnectErrorCode) (N.Socket, ConnectionRequestResponse))
810socketToEndPoint (EndPointAddress ourAddress) theirAddress = try $ do
814socketToEndPoint (EndPointAddress ourAddress) theirAddress = try $ do
811 (host, port, theirEndPointId) <- case decodeEndPointAddress theirAddress of
815 (host, port, theirEndPointId) <- case decodeEndPointAddress theirAddress of
812− Nothing -> throw (failed . userError $ "Could not parse")
816+ Nothing -> throwIO (failed . userError $ "Could not parse")
813 Just dec -> return dec
817 Just dec -> return dec
814 addr:_ <- mapExceptionIO invalidAddress $ N.getAddrInfo Nothing (Just host) (Just port)
818 addr:_ <- mapExceptionIO invalidAddress $ N.getAddrInfo Nothing (Just host) (Just port)
815 bracketOnError (createSocket addr) N.sClose $ \sock -> do
819 bracketOnError (createSocket addr) N.sClose $ \sock -> do
@@ -819,7 +823,7 @@ socketToEndPoint (EndPointAddress ourAddress) theirAddress = try $ do
819 sendMany sock (encodeInt32 theirEndPointId : prependLength [ourAddress])
823 sendMany sock (encodeInt32 theirEndPointId : prependLength [ourAddress])
820 recvInt32 sock
824 recvInt32 sock
821 case tryToEnum response of
825 case tryToEnum response of
822− Nothing -> throw (failed . userError $ "Unexpected response")
826+ Nothing -> throwIO (failed . userError $ "Unexpected response")
823 Just r -> return (sock, r)
827 Just r -> return (sock, r)
825 createSocket :: N.AddrInfo -> IO N.Socket
829 createSocket :: N.AddrInfo -> IO N.Socket
@@ -892,7 +896,7 @@ doRemoteRequest (ourEndPoint, theirEndPoint) header = do
892 let reqId = vst ^. nextCtrlRequestId
896 let reqId = vst ^. nextCtrlRequestId
893 return (LocalEndPointValid . (nextCtrlRequestId ^: (+ 1)) . (pendingCtrlRequestsAt reqId ^= Just reply) $ vst, reqId)
897 return (LocalEndPointValid . (nextCtrlRequestId ^: (+ 1)) . (pendingCtrlRequestsAt reqId ^= Just reply) $ vst, reqId)
894 LocalEndPointClosed ->
898 LocalEndPointClosed ->
895− throw (userError "Local endpoint closed")
899+ throwIO (userError "Local endpoint closed")
896 withRemoteState (ourEndPoint, theirEndPoint)
900 withRemoteState (ourEndPoint, theirEndPoint)
897 -- RemoteEndPointInvalid
901 -- RemoteEndPointInvalid
898 (\_ -> fail "doRemoteRequest RELY violation")
902 (\_ -> fail "doRemoteRequest RELY violation")
@@ -901,7 +905,7 @@ doRemoteRequest (ourEndPoint, theirEndPoint) header = do
901 -- RemoteEndPointClosing
905 -- RemoteEndPointClosing
902 (\_ -> fail "doRemoteRequest RELY violation")
906 (\_ -> fail "doRemoteRequest RELY violation")
903 -- RemoteEndPointClosed
907 -- RemoteEndPointClosed
904− (throw (userError "Remote endpoint closed"))
908+ (throwIO (userError "Remote endpoint closed"))
905 takeMVar reply
909 takeMVar reply
907-- | Check if the remote endpoint is unused, and if so, send a CloseSocket request
911-- | Check if the remote endpoint is unused, and if so, send a CloseSocket request
@@ -1012,7 +1016,7 @@ modifyRemoteState (ourEndPoint, theirEndPoint) caseInvalid caseValid caseClosing
1012 let err = TransportError (EventConnectionLost (remoteAddress theirEndPoint) incoming) (show ex)
1016 let err = TransportError (EventConnectionLost (remoteAddress theirEndPoint) incoming) (show ex)
1013 writeChan (localChannel ourEndPoint) $ ErrorEvent err
1017 writeChan (localChannel ourEndPoint) $ ErrorEvent err
1014 -- .. and finally rethrow the exception
1018 -- .. and finally rethrow the exception
1015− throw ex
1019+ throwIO ex
1017 -- Returns the set of incoming connections if we closed the connection, or
1021 -- Returns the set of incoming connections if we closed the connection, or
1018 -- 'Nothing' if the endpoint was already closed
1022 -- 'Nothing' if the endpoint was already closed