summaryrefslogtreecommitdiff
path: root/src/Network
diff options
context:
space:
mode:
authorSam Truzjan <pxqr.sta@gmail.com>2014-01-08 06:26:35 +0400
committerSam Truzjan <pxqr.sta@gmail.com>2014-01-08 06:26:35 +0400
commit6f909c0d81d04b997f8c81ec1ac05e94d7d1e5b6 (patch)
tree0926f49f12d629fd4813be043e7c5976d0455e14 /src/Network
parentfe87b6cec9504114dafca26166b51f6c48250106 (diff)
Add HandlerFailure exceptions
Diffstat (limited to 'src/Network')
-rw-r--r--src/Network/KRPC.hs13
-rw-r--r--src/Network/KRPC/Manager.hs60
-rw-r--r--src/Network/KRPC/Message.hs17
3 files changed, 57 insertions, 33 deletions
diff --git a/src/Network/KRPC.hs b/src/Network/KRPC.hs
index 96971803..69a4efca 100644
--- a/src/Network/KRPC.hs
+++ b/src/Network/KRPC.hs
@@ -56,13 +56,15 @@ module Network.KRPC
56 , KRPC (..) 56 , KRPC (..)
57 57
58 -- * RPC 58 -- * RPC
59 , Handler
60 , handler
61
62 -- ** Query 59 -- ** Query
63 , QueryFailure (..) 60 , QueryFailure (..)
64 , query 61 , query
65 62
63 -- ** Handler
64 , HandlerFailure (..)
65 , Handler
66 , handler
67
66 -- * Manager 68 -- * Manager
67 , MonadKRPC (..) 69 , MonadKRPC (..)
68 , Options (..) 70 , Options (..)
@@ -73,11 +75,8 @@ module Network.KRPC
73 , withManager 75 , withManager
74 , listen 76 , listen
75 77
76 -- * Exceptions 78 -- * Re-expor
77 , KError (..)
78 , ErrorCode (..) 79 , ErrorCode (..)
79
80 -- * Re-export
81 , SockAddr (..) 80 , SockAddr (..)
82 ) where 81 ) where
83 82
diff --git a/src/Network/KRPC/Manager.hs b/src/Network/KRPC/Manager.hs
index 6799277f..222b961a 100644
--- a/src/Network/KRPC/Manager.hs
+++ b/src/Network/KRPC/Manager.hs
@@ -31,6 +31,7 @@ module Network.KRPC.Manager
31 , query 31 , query
32 32
33 -- * Handlers 33 -- * Handlers
34 , HandlerFailure (..)
34 , Handler 35 , Handler
35 , handler 36 , handler
36 ) where 37 ) where
@@ -39,7 +40,8 @@ import Control.Applicative
39import Control.Concurrent 40import Control.Concurrent
40import Control.Concurrent.Lifted (fork) 41import Control.Concurrent.Lifted (fork)
41import Control.Exception hiding (Handler) 42import Control.Exception hiding (Handler)
42import Control.Exception.Lifted as Lifted (catch, finally) 43import qualified Control.Exception.Lifted as E (Handler (..))
44import Control.Exception.Lifted as Lifted (catches, finally)
43import Control.Monad 45import Control.Monad
44import Control.Monad.Logger 46import Control.Monad.Logger
45import Control.Monad.Reader 47import Control.Monad.Reader
@@ -288,9 +290,38 @@ query addr params = do
288{----------------------------------------------------------------------- 290{-----------------------------------------------------------------------
289-- Handlers 291-- Handlers
290-----------------------------------------------------------------------} 292-----------------------------------------------------------------------}
293-- we already throw:
294--
295-- * ErrorCode(MethodUnknown) in the 'dispatchHandler';
296--
297-- * ErrorCode(ServerError) in the 'runHandler'; (those can be
298-- async exception too)
299--
300-- * ErrorCode(GenericError) on
301
302-- | Used to signal protocol errors.
303data HandlerFailure
304 = BadAddress -- ^ for e.g.: node calls herself;
305 | InvalidParameter Text -- ^ for e.g.: bad session token.
306 deriving (Show, Eq, Typeable)
307
308instance Exception HandlerFailure
309
310prettyHF :: HandlerFailure -> BS.ByteString
311prettyHF BadAddress = T.encodeUtf8 "bad address"
312prettyHF (InvalidParameter reason) = T.encodeUtf8 $
313 "invalid parameter: " <> reason
314
315prettyQF :: QueryFailure -> BS.ByteString
316prettyQF e = T.encodeUtf8 $ "handler fail while performing query: "
317 <> T.pack (show e)
291 318
292-- | Make handler from handler function. Any thrown exception will be 319-- | Make handler from handler function. Any thrown exception will be
293-- supressed and send over the wire back to the querying node. 320-- supressed and send over the wire back to the querying node.
321--
322-- If the handler make some 'query' normally it /should/ handle
323-- corresponding 'QueryFailure's.
324--
294handler :: forall h a b. (KRPC a b, Monad h) 325handler :: forall h a b. (KRPC a b, Monad h)
295 => (SockAddr -> a -> h b) -> Handler h 326 => (SockAddr -> a -> h b) -> Handler h
296handler body = (name, wrapper) 327handler body = (name, wrapper)
@@ -305,7 +336,7 @@ handler body = (name, wrapper)
305 336
306runHandler :: MonadKRPC h m 337runHandler :: MonadKRPC h m
307 => HandlerBody h -> SockAddr -> KQuery -> m KResult 338 => HandlerBody h -> SockAddr -> KQuery -> m KResult
308runHandler h addr KQuery {..} = wrapper `Lifted.catch` failback 339runHandler h addr KQuery {..} = Lifted.catches wrapper failbacks
309 where 340 where
310 signature = querySignature queryMethod queryId addr 341 signature = querySignature queryMethod queryId addr
311 342
@@ -315,22 +346,33 @@ runHandler h addr KQuery {..} = wrapper `Lifted.catch` failback
315 346
316 case result of 347 case result of
317 Left msg -> do 348 Left msg -> do
318 $(logDebugS) "handler.failed" $ signature <> " !" <> T.pack msg 349 $(logDebugS) "handler.bad_query" $ signature <> " !" <> T.pack msg
319 return $ Left $ decodeError msg queryId 350 return $ Left $ KError ProtocolError (BC.pack msg) queryId
320 351
321 Right a -> do 352 Right a -> do
322 $(logDebugS) "handler.success" signature 353 $(logDebugS) "handler.success" signature
323 return $ Right $ a `KResponse` queryId 354 return $ Right $ KResponse a queryId
355
356 failbacks =
357 [ E.Handler $ \ (e :: HandlerFailure) -> do
358 $(logDebugS) "handler.failed" signature
359 return $ Left $ KError ProtocolError (prettyHF e) queryId
360
361 -- may happen if handler makes query and fail
362 , E.Handler $ \ (e :: QueryFailure) -> do
363 return $ Left $ KError ServerError (prettyQF e) queryId
324 364
325 failback e = do 365 -- since handler thread exit after sendMessage we can safely
326 $(logDebugS) "handler.errored" signature 366 -- suppress async exception here
327 return $ Left $ serverError e queryId 367 , E.Handler $ \ (e :: SomeException) -> do
368 return $ Left $ KError GenericError (BC.pack (show e)) queryId
369 ]
328 370
329dispatchHandler :: MonadKRPC h m => KQuery -> SockAddr -> m KResult 371dispatchHandler :: MonadKRPC h m => KQuery -> SockAddr -> m KResult
330dispatchHandler q @ KQuery {..} addr = do 372dispatchHandler q @ KQuery {..} addr = do
331 Manager {..} <- getManager 373 Manager {..} <- getManager
332 case L.lookup queryMethod handlers of 374 case L.lookup queryMethod handlers of
333 Nothing -> return $ Left $ unknownMethod queryMethod queryId 375 Nothing -> return $ Left $ KError MethodUnknown queryMethod queryId
334 Just h -> runHandler h addr q 376 Just h -> runHandler h addr q
335 377
336{----------------------------------------------------------------------- 378{-----------------------------------------------------------------------
diff --git a/src/Network/KRPC/Message.hs b/src/Network/KRPC/Message.hs
index d6279f11..96945843 100644
--- a/src/Network/KRPC/Message.hs
+++ b/src/Network/KRPC/Message.hs
@@ -26,11 +26,8 @@ module Network.KRPC.Message
26 -- * Error 26 -- * Error
27 , ErrorCode (..) 27 , ErrorCode (..)
28 , KError(..) 28 , KError(..)
29 , serverError
30 , decodeError 29 , decodeError
31 , unknownMethod
32 , unknownMessage 30 , unknownMessage
33 , timeoutExpired
34 31
35 -- * Query 32 -- * Query
36 , KQuery(..) 33 , KQuery(..)
@@ -143,29 +140,15 @@ instance BEncode KError where
143 140
144instance Exception KError 141instance Exception KError
145 142
146-- | Happen when some query handler fail.
147serverError :: SomeException -> TransactionId -> KError
148serverError e = KError ServerError (BC.pack (show e))
149
150-- | Received 'queryArgs' or 'respVals' can not be decoded. 143-- | Received 'queryArgs' or 'respVals' can not be decoded.
151decodeError :: String -> TransactionId -> KError 144decodeError :: String -> TransactionId -> KError
152decodeError msg = KError ProtocolError (BC.pack msg) 145decodeError msg = KError ProtocolError (BC.pack msg)
153 146
154-- | If /remote/ node send query /this/ node doesn't know about then
155-- this error message should be sent in response.
156unknownMethod :: MethodName -> TransactionId -> KError
157unknownMethod = KError MethodUnknown
158
159-- | A remote node has send some 'KMessage' this node is unable to 147-- | A remote node has send some 'KMessage' this node is unable to
160-- decode. 148-- decode.
161unknownMessage :: String -> KError 149unknownMessage :: String -> KError
162unknownMessage msg = KError ProtocolError (BC.pack msg) unknownTransaction 150unknownMessage msg = KError ProtocolError (BC.pack msg) unknownTransaction
163 151
164-- | A /remote/ node is not responding to the /our/ request the for
165-- specified period of time.
166timeoutExpired :: TransactionId -> KError
167timeoutExpired = KError GenericError "timeout expired"
168
169{----------------------------------------------------------------------- 152{-----------------------------------------------------------------------
170-- Query messages 153-- Query messages
171-----------------------------------------------------------------------} 154-----------------------------------------------------------------------}