summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Mainline.hs71
1 files changed, 63 insertions, 8 deletions
diff --git a/Mainline.hs b/Mainline.hs
index fdb77b4d..29f1df80 100644
--- a/Mainline.hs
+++ b/Mainline.hs
@@ -19,6 +19,7 @@ import Crypto.Random
19import Data.BEncode as BE 19import Data.BEncode as BE
20import qualified Data.BEncode.BDict as BE 20import qualified Data.BEncode.BDict as BE
21 ;import Data.BEncode.BDict (BKey) 21 ;import Data.BEncode.BDict (BKey)
22import Data.BEncode.Types (BDict)
22import Data.Bits 23import Data.Bits
23import Data.Bits.ByteString 24import Data.Bits.ByteString
24import Data.Bool 25import Data.Bool
@@ -64,6 +65,9 @@ instance S.Serialize NodeId where
64instance FiniteBits NodeId where 65instance FiniteBits NodeId where
65 finiteBitSize _ = 160 66 finiteBitSize _ = 160
66 67
68zeroID :: NodeId
69zeroID = NodeId $ B.replicate 20 0
70
67data NodeInfo = NodeInfo 71data NodeInfo = NodeInfo
68 { nodeId :: NodeId 72 { nodeId :: NodeId
69 , nodeIP :: IP 73 , nodeIP :: IP
@@ -183,17 +187,52 @@ data Message a = Q { msgOrigin :: NodeId
183 , rspReflectedIP :: Maybe SockAddr } 187 , rspReflectedIP :: Maybe SockAddr }
184 188
185instance BE.BEncode (Message BValue) where 189instance BE.BEncode (Message BValue) where
186 toBEncode = encodeMessage 190 toBEncode = encodeMessage
187 fromBEncode = error "TODO: fromBEncode (Mainline Message)" 191 fromBEncode = decodeMessage
188 192
193decodeMessage :: BValue -> Either String (Message BValue)
194decodeMessage = fromDict $ do
195 key <- lookAhead (field (req "y"))
196 let _ = key :: BKey
197 f <- case key of
198 "q" -> do a <- field (req "a")
199 g <- either fail return $ flip fromDict a $ do
200 who <- field (req "id")
201 ro <- fromMaybe False <$> optional (field (req "ro"))
202 return $ \meth tid -> Q who tid a meth ro
203 meth <- field (req "q")
204 return $ g meth
205 "r" -> do ip <- do
206 ipstr <- optional (field (req "ip"))
207 mapM (either fail return . decodeAddr) ipstr
208 vals <- field (req "r")
209 either fail return $ flip fromDict vals $ do
210 who <- field (req "id")
211 return $ \tid -> R who tid (Right vals) ip
212 "e" -> do (ecode,emsg) <- field (req "e")
213 ip <- do
214 ipstr <- optional (field (req "ip"))
215 mapM (either fail return . decodeAddr) ipstr
216 -- FIXME:Spec does not give us the NodeId of the sender.
217 -- Using 'zeroID' as place holder.
218 -- We should ignore the msgOrigin for errors in 'updateRouting'.
219 -- We should consider making msgOrigin a Maybe value.
220 return $ \tid -> R zeroID tid (Left (Error ecode emsg)) ip
221 _ -> fail $ "Mainline message is not a query, response, or an error: "
222 ++ show key
223 tid <- field (req "t")
224 return $ f (tid :: TransactionId)
225
226
227encodeMessage :: Message BValue -> BValue
189encodeMessage (Q origin tid a meth ro) 228encodeMessage (Q origin tid a meth ro)
190 = case a of 229 = case a of
191 BDict args -> encodeQuery tid meth (BDict $ genericArgs origin ro `BE.union` args) 230 BDict args -> encodeQuery tid meth (BDict $ genericArgs origin ro `BE.union` args)
192 _ -> encodeQuery tid meth a -- XXX: Not really a valid query. 231 _ -> encodeQuery tid meth a -- XXX: Not really a valid query.
193encodeMessage (R origin tid v ip) 232encodeMessage (R origin tid v ip)
194 = case v of 233 = case v of
195 Right vals -> encodeResponse tid vals (BString . encodeAddr <$> ip) 234 Right (BDict vals) -> encodeResponse tid (BDict $ genericArgs origin False `BE.union` vals) ip
196 Left err -> encodeError tid err 235 Left err -> encodeError tid err
197 236
198encodeAddr :: SockAddr -> ByteString 237encodeAddr :: SockAddr -> ByteString
199encodeAddr (SockAddrInet port addr) 238encodeAddr (SockAddrInet port addr)
@@ -202,17 +241,31 @@ encodeAddr (SockAddrInet6 port _ addr _)
202 = S.runPut (S.put addr >> S.put (fromIntegral port :: Word16)) 241 = S.runPut (S.put addr >> S.put (fromIntegral port :: Word16))
203encodeAddr _ = B.empty 242encodeAddr _ = B.empty
204 243
244decodeAddr :: ByteString -> Either String SockAddr
245decodeAddr = S.runGet $ do
246 error "decodeAddr"
247
248genericArgs :: BEncode a => a -> Bool -> BDict
205genericArgs nodeid ro = 249genericArgs nodeid ro =
206 "id" .=! nodeid 250 "id" .=! nodeid
207 .: "ro" .=? bool Nothing (Just (1 :: Int)) ro 251 .: "ro" .=? bool Nothing (Just (1 :: Int)) ro
208 .: endDict 252 .: endDict
209 253
210encodeError tid (Error ecode emsg) = encodeAny tid "e" (ecode,emsg) id 254encodeError :: BEncode a => a -> Error -> BValue
255encodeError tid (Error ecode emsg) = encodeAny tid "e" (ecode,emsg) id
211 256
212encodeResponse tid rvals rip = encodeAny tid "r" rvals ("ip" .=? rip .:) 257encodeResponse :: (BEncode tid, BEncode vals) =>
258 tid -> vals -> Maybe SockAddr -> BValue
259encodeResponse tid rvals rip =
260 encodeAny tid "r" rvals ("ip" .=? (BString . encodeAddr <$> rip) .:)
213 261
214encodeQuery tid qmeth qargs = encodeAny tid "q" qmeth ("a" .=! qargs .:) 262encodeQuery :: (BEncode args, BEncode tid, BEncode method) =>
263 tid -> method -> args -> BValue
264encodeQuery tid qmeth qargs = encodeAny tid "q" qmeth ("a" .=! qargs .:)
215 265
266encodeAny ::
267 (BEncode tid, BEncode a) =>
268 tid -> BKey -> a -> (BDict -> BDict) -> BValue
216encodeAny tid key val aux = toDict $ 269encodeAny tid key val aux = toDict $
217 aux $ key .=! val 270 aux $ key .=! val
218 .: "t" .=! tid 271 .: "t" .=! tid
@@ -221,6 +274,8 @@ encodeAny tid key val aux = toDict $
221 274
222parsePacket :: ByteString -> SockAddr -> Either String (Message BValue, NodeInfo) 275parsePacket :: ByteString -> SockAddr -> Either String (Message BValue, NodeInfo)
223parsePacket bs addr = do pkt <- BE.decode bs 276parsePacket bs addr = do pkt <- BE.decode bs
277 -- TODO: Error packets do not inclucde a valid msgOrigin.
278 -- The BE.decode method is using 'zeroID' as a placeholder.
224 ni <- nodeInfo (msgOrigin pkt) addr 279 ni <- nodeInfo (msgOrigin pkt) addr
225 return (pkt, ni) 280 return (pkt, ni)
226 281