summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSam T <pxqr.sta@gmail.com>2013-05-11 23:50:08 +0400
committerSam T <pxqr.sta@gmail.com>2013-05-11 23:50:08 +0400
commit7614ed760e137219fb4e36288abf1e78eacb2266 (patch)
tree13ec95709ae2e0c80131a17564af4ec0e514739a /src
parent3806b3513f04dd360badf438fa103334dd32933c (diff)
~ Catch server fails.
Diffstat (limited to 'src')
-rw-r--r--src/Remote/KRPC/Protocol.hs49
1 files changed, 32 insertions, 17 deletions
diff --git a/src/Remote/KRPC/Protocol.hs b/src/Remote/KRPC/Protocol.hs
index 8f6cc442..e7fbea11 100644
--- a/src/Remote/KRPC/Protocol.hs
+++ b/src/Remote/KRPC/Protocol.hs
@@ -25,9 +25,12 @@ module Remote.KRPC.Protocol
25 25
26 -- * Query 26 -- * Query
27 , KQuery(queryMethod, queryParams), MethodName, ParamName, kquery 27 , KQuery(queryMethod, queryParams), MethodName, ParamName, kquery
28 , KQueryScheme(qscMethod, qscParams)
28 29
29 -- * Response 30 -- * Response
30 , KResponse(..), ValName, kresponse 31 , KResponse(respVals), ValName, kresponse
32 , KResponseScheme(rscVals)
33
31 , sendMessage, recvResponse 34 , sendMessage, recvResponse
32 35
33 -- * Remote 36 -- * Remote
@@ -37,6 +40,7 @@ module Remote.KRPC.Protocol
37 , encode, encoded, decode, decoded, toBEncode, fromBEncode 40 , encode, encoded, decode, decoded, toBEncode, fromBEncode
38 ) where 41 ) where
39 42
43import Prelude hiding (catch)
40import Control.Applicative 44import Control.Applicative
41import Control.Exception.Lifted 45import Control.Exception.Lifted
42import Control.Monad 46import Control.Monad
@@ -71,10 +75,16 @@ class KMessage message scheme | message -> scheme where
71 75
72-- TODO document that it is and how transferred 76-- TODO document that it is and how transferred
73data KError 77data KError
78 -- | Some error doesn't fit in any other category.
74 = GenericError { errorMessage :: Text } 79 = GenericError { errorMessage :: Text }
80
81 -- | Occur when server fail to process procedure call.
75 | ServerError { errorMessage :: Text } 82 | ServerError { errorMessage :: Text }
83
76 -- | Malformed packet, invalid arguments or bad token. 84 -- | Malformed packet, invalid arguments or bad token.
77 | ProtocolError { errorMessage :: Text } 85 | ProtocolError { errorMessage :: Text }
86
87 -- | Occur when client trying to call method server don't know.
78 | MethodUnknown { errorMessage :: Text } 88 | MethodUnknown { errorMessage :: Text }
79 deriving (Show, Read, Eq, Ord) 89 deriving (Show, Read, Eq, Ord)
80 90
@@ -112,7 +122,8 @@ mkKError 204 = MethodUnknown
112mkKError _ = GenericError 122mkKError _ = GenericError
113{-# INLINE mkKError #-} 123{-# INLINE mkKError #-}
114 124
115 125serverError :: SomeException -> KError
126serverError = ServerError . T.pack . show
116 127
117-- TODO Asc everywhere 128-- TODO Asc everywhere
118 129
@@ -211,7 +222,11 @@ maxMsgSize = 16 * 1024
211sendMessage :: BEncodable msg => msg -> KRemoteAddr -> KRemote -> IO () 222sendMessage :: BEncodable msg => msg -> KRemoteAddr -> KRemote -> IO ()
212sendMessage msg (host, port) sock = 223sendMessage msg (host, port) sock =
213 sendAllTo sock (LB.toStrict (encoded msg)) (SockAddrInet port host) 224 sendAllTo sock (LB.toStrict (encoded msg)) (SockAddrInet port host)
225{-# INLINE sendMessage #-}
226{-# SPECIALIZE sendMessage :: BEncode -> KRemoteAddr -> KRemote -> IO () #-}
227
214 228
229-- TODO check scheme
215recvResponse :: KRemoteAddr -> KRemote -> IO (Either KError KResponse) 230recvResponse :: KRemoteAddr -> KRemote -> IO (Either KError KResponse)
216recvResponse addr sock = do 231recvResponse addr sock = do
217 connect sock (remoteAddr addr) 232 connect sock (remoteAddr addr)
@@ -222,6 +237,7 @@ recvResponse addr sock = do
222 Right kerror -> kerror 237 Right kerror -> kerror
223 _ -> ProtocolError (T.pack decE) 238 _ -> ProtocolError (T.pack decE)
224 239
240
225remoteServer :: (MonadBaseControl IO remote, MonadIO remote) 241remoteServer :: (MonadBaseControl IO remote, MonadIO remote)
226 => PortNumber 242 => PortNumber
227 -> (KRemoteAddr -> KQuery -> remote (Either KError KResponse)) 243 -> (KRemoteAddr -> KQuery -> remote (Either KError KResponse))
@@ -235,24 +251,23 @@ remoteServer servport action = bracket (liftIO bind) (liftIO . sClose) loop
235 251
236 loop sock = forever $ do 252 loop sock = forever $ do
237 (bs, addr) <- liftIO $ recvFrom sock maxMsgSize 253 (bs, addr) <- liftIO $ recvFrom sock maxMsgSize
238
239 case addr of 254 case addr of
240 SockAddrInet port host -> 255 SockAddrInet port host -> do
241 case decoded bs of 256 let kaddr = (host, port)
242 Right query -> do 257 reply <- handleMsg bs kaddr
243 res <- action (host, port) query 258 liftIO $ sendMessage reply kaddr sock
244 case res of
245 Right resp -> liftIO $ sendMessage resp (host, port) sock
246 Left err -> liftIO $ sendMessage err (host, port) sock
247
248 Left decodeE -> liftIO $ sendMessage rpcE (host, port) sock
249 where
250 rpcE = ProtocolError $ T.concat
251 ["Unable to decode query: ", T.pack (show bs), "\n"
252 ,"Specifically: ", T.pack decodeE
253 ]
254 _ -> return () 259 _ -> return ()
255 260
261 where
262 handleMsg bs addr = case decoded bs of
263 Right query -> (either toBEncode toBEncode <$> action addr query)
264 `catch` (return . toBEncode . serverError)
265 Left decodeE -> return $ toBEncode rpcE
266 where
267 rpcE = ProtocolError $ T.concat
268 ["Unable to decode query: ", T.pack (show bs), "\n"
269 ,"Specifically: ", T.pack decodeE
270 ]
256 271
257 272
258-- TODO to bencodable 273-- TODO to bencodable