diff options
Diffstat (limited to 'src/Network/KRPC/Protocol.hs')
-rw-r--r-- | src/Network/KRPC/Protocol.hs | 81 |
1 files changed, 40 insertions, 41 deletions
diff --git a/src/Network/KRPC/Protocol.hs b/src/Network/KRPC/Protocol.hs index 1e7bd7c3..67a4057d 100644 --- a/src/Network/KRPC/Protocol.hs +++ b/src/Network/KRPC/Protocol.hs | |||
@@ -17,6 +17,7 @@ | |||
17 | {-# LANGUAGE MultiParamTypeClasses #-} | 17 | {-# LANGUAGE MultiParamTypeClasses #-} |
18 | {-# LANGUAGE FunctionalDependencies #-} | 18 | {-# LANGUAGE FunctionalDependencies #-} |
19 | {-# LANGUAGE DefaultSignatures #-} | 19 | {-# LANGUAGE DefaultSignatures #-} |
20 | {-# LANGUAGE DeriveDataTypeable #-} | ||
20 | module Network.KRPC.Protocol | 21 | module Network.KRPC.Protocol |
21 | ( -- * Error | 22 | ( -- * Error |
22 | KError(..) | 23 | KError(..) |
@@ -46,9 +47,7 @@ module Network.KRPC.Protocol | |||
46 | 47 | ||
47 | -- * Re-exports | 48 | -- * Re-exports |
48 | , encode | 49 | , encode |
49 | , encoded | ||
50 | , decode | 50 | , decode |
51 | , decoded | ||
52 | , toBEncode | 51 | , toBEncode |
53 | , fromBEncode | 52 | , fromBEncode |
54 | ) where | 53 | ) where |
@@ -59,11 +58,14 @@ import Control.Monad | |||
59 | import Control.Monad.IO.Class | 58 | import Control.Monad.IO.Class |
60 | import Control.Monad.Trans.Control | 59 | import Control.Monad.Trans.Control |
61 | 60 | ||
62 | import Data.BEncode | 61 | import Data.BEncode as BE |
62 | import Data.BEncode.BDict as BE | ||
63 | import Data.BEncode.Types as BE | ||
63 | import Data.ByteString as B | 64 | import Data.ByteString as B |
64 | import Data.ByteString.Char8 as BC | 65 | import Data.ByteString.Char8 as BC |
65 | import qualified Data.ByteString.Lazy as LB | 66 | import qualified Data.ByteString.Lazy as LB |
66 | import Data.Map as M | 67 | import Data.Map as M |
68 | import Data.Typeable | ||
67 | 69 | ||
68 | import Network.Socket hiding (recvFrom) | 70 | import Network.Socket hiding (recvFrom) |
69 | import Network.Socket.ByteString | 71 | import Network.Socket.ByteString |
@@ -89,20 +91,21 @@ data KError | |||
89 | 91 | ||
90 | -- | Occur when client trying to call method server don't know. | 92 | -- | Occur when client trying to call method server don't know. |
91 | | MethodUnknown { errorMessage :: ByteString } | 93 | | MethodUnknown { errorMessage :: ByteString } |
92 | deriving (Show, Read, Eq, Ord) | 94 | deriving (Show, Read, Eq, Ord, Typeable) |
93 | 95 | ||
94 | instance BEncode KError where | 96 | instance BEncode KError where |
95 | {-# SPECIALIZE instance BEncode KError #-} | 97 | {-# SPECIALIZE instance BEncode KError #-} |
96 | {-# INLINE toBEncode #-} | 98 | {-# INLINE toBEncode #-} |
97 | toBEncode e = fromAscAssocs -- WARN: keep keys sorted | 99 | toBEncode e = toDict $ |
98 | [ "e" --> (errorCode e, errorMessage e) | 100 | "e" .=! (errorCode e, errorMessage e) |
99 | , "y" --> ("e" :: ByteString) | 101 | .: "y" .=! ("e" :: ByteString) |
100 | ] | 102 | .: endDict |
101 | 103 | ||
102 | {-# INLINE fromBEncode #-} | 104 | {-# INLINE fromBEncode #-} |
103 | fromBEncode (BDict d) | 105 | fromBEncode be @ (BDict d) |
104 | | M.lookup "y" d == Just (BString "e") | 106 | | BE.lookup "y" d == Just (BString "e") |
105 | = uncurry mkKError <$> d >-- "e" | 107 | = (`fromDict` be) $ do |
108 | uncurry mkKError <$>! "e" | ||
106 | 109 | ||
107 | fromBEncode _ = decodingError "KError" | 110 | fromBEncode _ = decodingError "KError" |
108 | 111 | ||
@@ -140,33 +143,30 @@ type ParamName = ByteString | |||
140 | -- | 143 | -- |
141 | data KQuery = KQuery { | 144 | data KQuery = KQuery { |
142 | queryMethod :: MethodName | 145 | queryMethod :: MethodName |
143 | , queryArgs :: Map ParamName BValue | 146 | , queryArgs :: BDict |
144 | } deriving (Show, Read, Eq, Ord) | 147 | } deriving (Show, Read, Eq, Ord, Typeable) |
145 | 148 | ||
146 | instance BEncode KQuery where | 149 | instance BEncode KQuery where |
147 | {-# SPECIALIZE instance BEncode KQuery #-} | 150 | {-# SPECIALIZE instance BEncode KQuery #-} |
148 | {-# INLINE toBEncode #-} | 151 | {-# INLINE toBEncode #-} |
149 | toBEncode (KQuery m args) = fromAscAssocs -- WARN: keep keys sorted | 152 | toBEncode (KQuery m args) = toDict $ |
150 | [ "a" --> BDict args | 153 | "a" .=! BDict args |
151 | , "q" --> m | 154 | .: "q" .=! m |
152 | , "y" --> ("q" :: ByteString) | 155 | .: "y" .=! ("q" :: ByteString) |
153 | ] | 156 | .: endDict |
154 | 157 | ||
155 | {-# INLINE fromBEncode #-} | 158 | {-# INLINE fromBEncode #-} |
156 | fromBEncode (BDict d) | 159 | fromBEncode bv @ (BDict d) |
157 | | M.lookup "y" d == Just (BString "q") = | 160 | | BE.lookup "y" d == Just (BString "q") = (`fromDict` bv) $ do |
158 | KQuery <$> d >-- "q" | 161 | KQuery <$>! "q" <*>! "a" |
159 | <*> d >-- "a" | ||
160 | 162 | ||
161 | fromBEncode _ = decodingError "KQuery" | 163 | fromBEncode _ = decodingError "KQuery" |
162 | 164 | ||
163 | kquery :: MethodName -> [(ParamName, BValue)] -> KQuery | 165 | kquery :: MethodName -> BDict -> KQuery |
164 | kquery name args = KQuery name (M.fromList args) | 166 | kquery = KQuery |
165 | {-# INLINE kquery #-} | 167 | {-# INLINE kquery #-} |
166 | 168 | ||
167 | 169 | ||
168 | |||
169 | |||
170 | type ValName = ByteString | 170 | type ValName = ByteString |
171 | 171 | ||
172 | -- | KResponse used to signal that callee successufully process a | 172 | -- | KResponse used to signal that callee successufully process a |
@@ -179,25 +179,24 @@ type ValName = ByteString | |||
179 | -- > { "y" : "r", "r" : [<val1>, <val2>, ...] } | 179 | -- > { "y" : "r", "r" : [<val1>, <val2>, ...] } |
180 | -- | 180 | -- |
181 | newtype KResponse = KResponse { respVals :: BDict } | 181 | newtype KResponse = KResponse { respVals :: BDict } |
182 | deriving (Show, Read, Eq, Ord) | 182 | deriving (Show, Read, Eq, Ord, Typeable) |
183 | 183 | ||
184 | instance BEncode KResponse where | 184 | instance BEncode KResponse where |
185 | {-# INLINE toBEncode #-} | 185 | {-# INLINE toBEncode #-} |
186 | toBEncode (KResponse vals) = fromAscAssocs -- WARN: keep keys sorted | 186 | toBEncode (KResponse vals) = toDict $ |
187 | [ "r" --> vals | 187 | "r" .=! vals |
188 | , "y" --> ("r" :: ByteString) | 188 | .: "y" .=! ("r" :: ByteString) |
189 | ] | 189 | .: endDict |
190 | 190 | ||
191 | {-# INLINE fromBEncode #-} | 191 | {-# INLINE fromBEncode #-} |
192 | fromBEncode (BDict d) | 192 | fromBEncode bv @ (BDict d) |
193 | | M.lookup "y" d == Just (BString "r") = | 193 | | BE.lookup "y" d == Just (BString "r") = (`fromDict` bv) $ do |
194 | KResponse <$> d >-- "r" | 194 | KResponse <$>! "r" |
195 | 195 | ||
196 | fromBEncode _ = decodingError "KDict" | 196 | fromBEncode _ = decodingError "KDict" |
197 | 197 | ||
198 | 198 | kresponse :: BDict -> KResponse | |
199 | kresponse :: [(ValName, BValue)] -> KResponse | 199 | kresponse = KResponse |
200 | kresponse = KResponse . M.fromList | ||
201 | {-# INLINE kresponse #-} | 200 | {-# INLINE kresponse #-} |
202 | 201 | ||
203 | type KRemoteAddr = SockAddr | 202 | type KRemoteAddr = SockAddr |
@@ -219,15 +218,15 @@ maxMsgSize = 64 * 1024 -- bench: max UDP MTU | |||
219 | {-# INLINE maxMsgSize #-} | 218 | {-# INLINE maxMsgSize #-} |
220 | 219 | ||
221 | sendMessage :: BEncode msg => msg -> KRemoteAddr -> KRemote -> IO () | 220 | sendMessage :: BEncode msg => msg -> KRemoteAddr -> KRemote -> IO () |
222 | sendMessage msg addr sock = sendManyTo sock (LB.toChunks (encoded msg)) addr | 221 | sendMessage msg addr sock = sendManyTo sock (LB.toChunks (encode msg)) addr |
223 | {-# INLINE sendMessage #-} | 222 | {-# INLINE sendMessage #-} |
224 | 223 | ||
225 | recvResponse :: KRemote -> IO (Either KError KResponse) | 224 | recvResponse :: KRemote -> IO (Either KError KResponse) |
226 | recvResponse sock = do | 225 | recvResponse sock = do |
227 | (raw, _) <- recvFrom sock maxMsgSize | 226 | (raw, _) <- recvFrom sock maxMsgSize |
228 | return $ case decoded raw of | 227 | return $ case decode raw of |
229 | Right resp -> Right resp | 228 | Right resp -> Right resp |
230 | Left decE -> Left $ case decoded raw of | 229 | Left decE -> Left $ case decode raw of |
231 | Right kerror -> kerror | 230 | Right kerror -> kerror |
232 | _ -> ProtocolError (BC.pack decE) | 231 | _ -> ProtocolError (BC.pack decE) |
233 | 232 | ||
@@ -252,7 +251,7 @@ remoteServer servAddr action = bracket (liftIO bindServ) (liftIO . sClose) loop | |||
252 | reply <- handleMsg bs addr | 251 | reply <- handleMsg bs addr |
253 | liftIO $ sendMessage reply addr sock | 252 | liftIO $ sendMessage reply addr sock |
254 | where | 253 | where |
255 | handleMsg bs addr = case decoded bs of | 254 | handleMsg bs addr = case decode bs of |
256 | Right query -> (either toBEncode toBEncode <$> action addr query) | 255 | Right query -> (either toBEncode toBEncode <$> action addr query) |
257 | `Lifted.catch` (return . toBEncode . serverError) | 256 | `Lifted.catch` (return . toBEncode . serverError) |
258 | Left decodeE -> return $ toBEncode (ProtocolError (BC.pack decodeE)) | 257 | Left decodeE -> return $ toBEncode (ProtocolError (BC.pack decodeE)) |