summaryrefslogtreecommitdiff
path: root/Mainline.hs
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-07-25 22:10:22 -0400
committerjoe <joe@jerkface.net>2017-07-25 22:10:22 -0400
commit66e9813be8b61e57f7cf61bb4b21dc90f3e79d30 (patch)
treeb45fe067877e45c5f6f16c441e17c14406800d77 /Mainline.hs
parent480088a97f9622b7bb56978f3596e87ee7c770a0 (diff)
Bootstrap fixes.
Diffstat (limited to 'Mainline.hs')
-rw-r--r--Mainline.hs68
1 files changed, 59 insertions, 9 deletions
diff --git a/Mainline.hs b/Mainline.hs
index 911f0dbc..b24f847d 100644
--- a/Mainline.hs
+++ b/Mainline.hs
@@ -73,6 +73,9 @@ import Control.Concurrent.Lifted
73import GHC.Conc (labelThread) 73import GHC.Conc (labelThread)
74#endif 74#endif
75import Control.Exception (SomeException(..),handle) 75import Control.Exception (SomeException(..),handle)
76import Data.Aeson (FromJSON,ToJSON,(.=))
77import qualified Data.Aeson as JSON
78import Text.Read
76 79
77newtype NodeId = NodeId ByteString 80newtype NodeId = NodeId ByteString
78 deriving (Eq,Ord,ByteArrayAccess, BEncode, Bits, Hashable) 81 deriving (Eq,Ord,ByteArrayAccess, BEncode, Bits, Hashable)
@@ -97,6 +100,36 @@ data NodeInfo = NodeInfo
97 } 100 }
98 deriving (Eq,Ord) 101 deriving (Eq,Ord)
99 102
103instance ToJSON NodeInfo where
104 toJSON (NodeInfo nid (IPv4 ip) port)
105 = JSON.object [ "node-id" .= show nid
106 , "ipv4" .= show ip
107 , "port" .= (fromIntegral port :: Int)
108 ]
109 toJSON (NodeInfo nid (IPv6 ip6) port)
110 | Just ip <- un4map ip6
111 = JSON.object [ "node-id" .= show nid
112 , "ipv4" .= show ip
113 , "port" .= (fromIntegral port :: Int)
114 ]
115 | otherwise
116 = JSON.object [ "node-id" .= show nid
117 , "ipv6" .= show ip6
118 , "port" .= (fromIntegral port :: Int)
119 ]
120instance FromJSON NodeInfo where
121 parseJSON (JSON.Object v) = do
122 nidstr <- v JSON..: "node-id"
123 ip6str <- v JSON..:? "ipv6"
124 ip4str <- v JSON..:? "ipv4"
125 portnum <- v JSON..: "port"
126 ip <- maybe empty (return . IPv6) (ip6str >>= readMaybe)
127 <|> maybe empty (return . IPv4) (ip4str >>= readMaybe)
128 let (bs,_) = Base16.decode (Char8.pack nidstr)
129 guard (B.length bs == 20)
130 return $ NodeInfo (NodeId bs) ip (fromIntegral (portnum :: Word16))
131
132
100-- The Hashable instance depends only on the IP address and port number. It is 133-- The Hashable instance depends only on the IP address and port number. It is
101-- used to compute the announce token. 134-- used to compute the announce token.
102instance Hashable NodeInfo where 135instance Hashable NodeInfo where
@@ -145,11 +178,14 @@ putNodeInfo6 (NodeInfo (NodeId nid) (IPv6 ip) port)
145putNodeInfo6 _ = return () 178putNodeInfo6 _ = return ()
146 179
147 180
148-- TODO: We should use a SocketAddrInet6 address for a dual-stack listen 181-- | TODO: This should depend on the bind address to support IPv4-only. For
149-- socket. Therefore, the behavior of this method should depend on the bind 182-- now, in order to support dual-stack listen, we're going to assume IPv6 is
150-- address for outbound packets. 183-- wanted and map IPv4 addresses accordingly.
151nodeAddr :: NodeInfo -> SockAddr 184nodeAddr :: NodeInfo -> SockAddr
152nodeAddr (NodeInfo _ ip port) = setPort port $ toSockAddr ip 185nodeAddr (NodeInfo _ ip port) =
186 case ip of
187 IPv4 ip4 -> setPort port $ toSockAddr (ipv4ToIPv6 ip4)
188 IPv6 ip6 -> setPort port $ toSockAddr ip6
153 189
154nodeInfo :: NodeId -> SockAddr -> Either String NodeInfo 190nodeInfo :: NodeId -> SockAddr -> Either String NodeInfo
155nodeInfo nid saddr 191nodeInfo nid saddr
@@ -503,6 +539,16 @@ newClient addr = do
503 539
504-- | Modifies a purely random 'NodeId' to one that is related to a given 540-- | Modifies a purely random 'NodeId' to one that is related to a given
505-- routable address in accordance with BEP 42. 541-- routable address in accordance with BEP 42.
542--
543-- Test vectors from the spec:
544--
545-- IP rand example node ID
546-- ============ ===== ==========================================
547-- 124.31.75.21 1 5fbfbf f10c5d6a4ec8a88e4c6ab4c28b95eee4 01
548-- 21.75.31.124 86 5a3ce9 c14e7a08645677bbd1cfe7d8f956d532 56
549-- 65.23.51.170 22 a5d432 20bc8f112a3d426c84764f8c2a1150e6 16
550-- 84.124.73.14 65 1b0321 dd1bb1fe518101ceef99462b947a01ff 41
551-- 43.213.53.83 90 e56f6c bf5b7c4be0237986d5243b87aa6d5130 5a
506bep42 :: SockAddr -> NodeId -> Maybe NodeId 552bep42 :: SockAddr -> NodeId -> Maybe NodeId
507bep42 addr (NodeId r) 553bep42 addr (NodeId r)
508 | Just ip <- fmap S.encode (fromSockAddr addr :: Maybe IPv4) 554 | Just ip <- fmap S.encode (fromSockAddr addr :: Maybe IPv4)
@@ -513,10 +559,9 @@ bep42 addr (NodeId r)
513 where 559 where
514 ip4mask = "\x03\x0f\x3f\xff" :: ByteString 560 ip4mask = "\x03\x0f\x3f\xff" :: ByteString
515 ip6mask = "\x01\x03\x07\x0f\x1f\x3f\x7f\xff" :: ByteString 561 ip6mask = "\x01\x03\x07\x0f\x1f\x3f\x7f\xff" :: ByteString
516 nbhood_select = (B.last r :: Word8) .&. 7 562 nbhood_select = B.last r .&. 7
517 nodeIdSize = 20 563 retr n = pure $ B.drop (B.length r - n) r
518 retr n = pure $ B.drop (nodeIdSize - n) $ S.encode r 564 crc = S.encode . crc32c . B.pack
519 crc = (`B.append` B.replicate 16 0) . S.encode . crc32c . B.pack
520 applyMask ip = case B.zipWith (.&.) msk ip of 565 applyMask ip = case B.zipWith (.&.) msk ip of
521 (b:bs) -> (b .|. shiftL nbhood_select 5) : bs 566 (b:bs) -> (b .|. shiftL nbhood_select 5) : bs
522 bs -> bs 567 bs -> bs
@@ -524,6 +569,7 @@ bep42 addr (NodeId r)
524 | otherwise = ip6mask 569 | otherwise = ip6mask
525 570
526 571
572
527defaultHandler :: ByteString -> Handler 573defaultHandler :: ByteString -> Handler
528defaultHandler meth = MethodHandler decodePayload errorPayload returnError 574defaultHandler meth = MethodHandler decodePayload errorPayload returnError
529 where 575 where
@@ -540,7 +586,11 @@ mainlineKademlia client committee var sched
540 io2 <- touchBucket mainlineSpace (15*60) var sched tr 586 io2 <- touchBucket mainlineSpace (15*60) var sched tr
541 return $ do 587 return $ do
542 io1 >> io2 588 io1 >> io2
543 hPutStrLn stderr ("Buckets: "++show tr) 589 hPutStrLn stderr $ unwords
590 [ "Buckets: "
591 , show (transitionedTo tr)
592 , show (transitioningNode tr)
593 ]
544 } 594 }
545 595
546 596