diff options
author | joe <joe@jerkface.net> | 2017-01-03 23:58:37 -0500 |
---|---|---|
committer | joe <joe@jerkface.net> | 2017-01-03 23:58:37 -0500 |
commit | eb774b28dc02d1a5c0ad9c8178b1df3c0782b6eb (patch) | |
tree | bcb7a2fc2575ef8f352f2ad09033c6e62e7cfc4c /src/Network/BitTorrent/DHT | |
parent | 59f2763351ef1e3ba21f77e2273f3c523ac9df9d (diff) |
Don't use BEP 43 read-only nodes for routing.
Diffstat (limited to 'src/Network/BitTorrent/DHT')
-rw-r--r-- | src/Network/BitTorrent/DHT/Message.hs | 18 | ||||
-rw-r--r-- | src/Network/BitTorrent/DHT/Query.hs | 11 | ||||
-rw-r--r-- | src/Network/BitTorrent/DHT/Session.hs | 3 |
3 files changed, 23 insertions, 9 deletions
diff --git a/src/Network/BitTorrent/DHT/Message.hs b/src/Network/BitTorrent/DHT/Message.hs index 008145de..b8f272c3 100644 --- a/src/Network/BitTorrent/DHT/Message.hs +++ b/src/Network/BitTorrent/DHT/Message.hs | |||
@@ -92,6 +92,7 @@ import Data.Serialize as S | |||
92 | import Data.Typeable | 92 | import Data.Typeable |
93 | import Network | 93 | import Network |
94 | import Network.KRPC | 94 | import Network.KRPC |
95 | import Data.Maybe | ||
95 | 96 | ||
96 | import Data.Torrent | 97 | import Data.Torrent |
97 | import Network.BitTorrent.Address | 98 | import Network.BitTorrent.Address |
@@ -105,11 +106,16 @@ import Network.KRPC () | |||
105 | node_id_key :: BKey | 106 | node_id_key :: BKey |
106 | node_id_key = "id" | 107 | node_id_key = "id" |
107 | 108 | ||
109 | read_only_key :: BKey | ||
110 | read_only_key = "ro" | ||
111 | |||
112 | |||
108 | -- | All queries have an \"id\" key and value containing the node ID | 113 | -- | All queries have an \"id\" key and value containing the node ID |
109 | -- of the querying node. | 114 | -- of the querying node. |
110 | data Query a = Query | 115 | data Query a = Query |
111 | { queringNodeId :: NodeId -- ^ node id of /quering/ node; | 116 | { queringNodeId :: NodeId -- ^ node id of /quering/ node; |
112 | , queryParams :: a -- ^ query parameters. | 117 | , queryIsReadOnly :: Bool -- ^ node is read-only as per BEP 43 |
118 | , queryParams :: a -- ^ query parameters. | ||
113 | } deriving (Show, Eq, Typeable) | 119 | } deriving (Show, Eq, Typeable) |
114 | 120 | ||
115 | instance BEncode a => BEncode (Query a) where | 121 | instance BEncode a => BEncode (Query a) where |
@@ -118,11 +124,13 @@ instance BEncode a => BEncode (Query a) where | |||
118 | <> | 124 | <> |
119 | dict (toBEncode queryParams) | 125 | dict (toBEncode queryParams) |
120 | where | 126 | where |
121 | dict (BDict d) = d | 127 | dict (BDict d) | queryIsReadOnly = Cons read_only_key (BInteger 1) d |
128 | | otherwise = d | ||
122 | dict _ = error "impossible: instance BEncode (Query a)" | 129 | dict _ = error "impossible: instance BEncode (Query a)" |
123 | 130 | ||
124 | fromBEncode v = do | 131 | fromBEncode v = do |
125 | Query <$> fromDict (field (req node_id_key)) v | 132 | Query <$> fromDict (field (req node_id_key)) v |
133 | <*> fromDict (fromMaybe False <$>? read_only_key) v | ||
126 | <*> fromBEncode v | 134 | <*> fromBEncode v |
127 | 135 | ||
128 | -- | All responses have an \"id\" key and value containing the node ID | 136 | -- | All responses have an \"id\" key and value containing the node ID |
@@ -135,11 +143,11 @@ data Response a = Response | |||
135 | instance BEncode a => BEncode (Response a) where | 143 | instance BEncode a => BEncode (Response a) where |
136 | toBEncode = toBEncode . toQuery | 144 | toBEncode = toBEncode . toQuery |
137 | where | 145 | where |
138 | toQuery (Response nid a) = Query nid a | 146 | toQuery (Response nid a) = Query nid False a |
139 | 147 | ||
140 | fromBEncode b = fromQuery <$> fromBEncode b | 148 | fromBEncode b = fromQuery <$> fromBEncode b |
141 | where | 149 | where |
142 | fromQuery (Query nid a) = Response nid a | 150 | fromQuery (Query nid _ a) = Response nid a |
143 | 151 | ||
144 | 152 | ||
145 | {----------------------------------------------------------------------- | 153 | {----------------------------------------------------------------------- |
diff --git a/src/Network/BitTorrent/DHT/Query.hs b/src/Network/BitTorrent/DHT/Query.hs index cb7d5c5f..d51ab505 100644 --- a/src/Network/BitTorrent/DHT/Query.hs +++ b/src/Network/BitTorrent/DHT/Query.hs | |||
@@ -68,11 +68,15 @@ import Network.BitTorrent.DHT.Session | |||
68 | 68 | ||
69 | nodeHandler :: Address ip => KRPC (Query a) (Response b) | 69 | nodeHandler :: Address ip => KRPC (Query a) (Response b) |
70 | => (NodeAddr ip -> a -> DHT ip b) -> NodeHandler ip | 70 | => (NodeAddr ip -> a -> DHT ip b) -> NodeHandler ip |
71 | nodeHandler action = handler $ \ sockAddr (Query remoteId q) -> do | 71 | nodeHandler action = handler $ \ sockAddr (Query remoteId read_only q) -> do |
72 | case fromSockAddr sockAddr of | 72 | case fromSockAddr sockAddr of |
73 | Nothing -> throwIO BadAddress | 73 | Nothing -> throwIO BadAddress |
74 | Just naddr -> do | 74 | Just naddr -> do |
75 | insertNode (NodeInfo remoteId naddr) -- TODO need to block. why? | 75 | let ni = NodeInfo remoteId naddr |
76 | -- Do not route read-only nodes. (bep 43) | ||
77 | if read_only | ||
78 | then $(logWarnS) "nodeHandler" $ "READ-ONLY " <> T.pack (show $ pPrint ni) | ||
79 | else insertNode ni >> return () -- TODO need to block. why? | ||
76 | Response <$> asks thisNodeId <*> action naddr q | 80 | Response <$> asks thisNodeId <*> action naddr q |
77 | 81 | ||
78 | -- | Default 'Ping' handler. | 82 | -- | Default 'Ping' handler. |
@@ -125,6 +129,7 @@ pingQ addr = do | |||
125 | findNodeQ :: Address ip => TableKey key => key -> Iteration ip NodeInfo | 129 | findNodeQ :: Address ip => TableKey key => key -> Iteration ip NodeInfo |
126 | findNodeQ key NodeInfo {..} = do | 130 | findNodeQ key NodeInfo {..} = do |
127 | NodeFound closest <- FindNode (toNodeId key) <@> nodeAddr | 131 | NodeFound closest <- FindNode (toNodeId key) <@> nodeAddr |
132 | $(logInfoS) "findNodeQ" $ "NodeFound " <> T.pack (show $ L.map pPrint closest) | ||
128 | return $ Right closest | 133 | return $ Right closest |
129 | 134 | ||
130 | getPeersQ :: Address ip => InfoHash -> Iteration ip PeerAddr | 135 | getPeersQ :: Address ip => InfoHash -> Iteration ip PeerAddr |
@@ -155,7 +160,7 @@ type Search ip o = Conduit [NodeInfo ip] (DHT ip) [o ip] | |||
155 | 160 | ||
156 | -- TODO: use reorder and filter (Traversal option) leftovers | 161 | -- TODO: use reorder and filter (Traversal option) leftovers |
157 | search :: TableKey k => Address ip => k -> Iteration ip o -> Search ip o | 162 | search :: TableKey k => Address ip => k -> Iteration ip o -> Search ip o |
158 | search k action = do | 163 | search _ action = do |
159 | awaitForever $ \ batch -> unless (L.null batch) $ do | 164 | awaitForever $ \ batch -> unless (L.null batch) $ do |
160 | $(logWarnS) "search" "start query" | 165 | $(logWarnS) "search" "start query" |
161 | responses <- lift $ queryParallel (action <$> batch) | 166 | responses <- lift $ queryParallel (action <$> batch) |
diff --git a/src/Network/BitTorrent/DHT/Session.hs b/src/Network/BitTorrent/DHT/Session.hs index 42270ae8..ffce47de 100644 --- a/src/Network/BitTorrent/DHT/Session.hs +++ b/src/Network/BitTorrent/DHT/Session.hs | |||
@@ -492,7 +492,8 @@ queryNode :: forall a b ip. Address ip => KRPC (Query a) (Response b) | |||
492 | => NodeAddr ip -> a -> DHT ip (NodeId, b) | 492 | => NodeAddr ip -> a -> DHT ip (NodeId, b) |
493 | queryNode addr q = do | 493 | queryNode addr q = do |
494 | nid <- asks thisNodeId | 494 | nid <- asks thisNodeId |
495 | Response remoteId r <- query (toSockAddr addr) (Query nid q) | 495 | let read_only = False -- TODO: check for NAT issues. (BEP 43) |
496 | Response remoteId r <- query (toSockAddr addr) (Query nid read_only q) | ||
496 | insertNode (NodeInfo remoteId addr) | 497 | insertNode (NodeInfo remoteId addr) |
497 | return (remoteId, r) | 498 | return (remoteId, r) |
498 | 499 | ||