diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Remote/KRPC/Protocol.hs | 49 |
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 | ||
43 | import Prelude hiding (catch) | ||
40 | import Control.Applicative | 44 | import Control.Applicative |
41 | import Control.Exception.Lifted | 45 | import Control.Exception.Lifted |
42 | import Control.Monad | 46 | import 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 |
73 | data KError | 77 | data 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 | |||
112 | mkKError _ = GenericError | 122 | mkKError _ = GenericError |
113 | {-# INLINE mkKError #-} | 123 | {-# INLINE mkKError #-} |
114 | 124 | ||
115 | 125 | serverError :: SomeException -> KError | |
126 | serverError = ServerError . T.pack . show | ||
116 | 127 | ||
117 | -- TODO Asc everywhere | 128 | -- TODO Asc everywhere |
118 | 129 | ||
@@ -211,7 +222,11 @@ maxMsgSize = 16 * 1024 | |||
211 | sendMessage :: BEncodable msg => msg -> KRemoteAddr -> KRemote -> IO () | 222 | sendMessage :: BEncodable msg => msg -> KRemoteAddr -> KRemote -> IO () |
212 | sendMessage msg (host, port) sock = | 223 | sendMessage 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 | ||
215 | recvResponse :: KRemoteAddr -> KRemote -> IO (Either KError KResponse) | 230 | recvResponse :: KRemoteAddr -> KRemote -> IO (Either KError KResponse) |
216 | recvResponse addr sock = do | 231 | recvResponse 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 | |||
225 | remoteServer :: (MonadBaseControl IO remote, MonadIO remote) | 241 | remoteServer :: (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 |