summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Network/BitTorrent/DHT/Message.hs18
-rw-r--r--src/Network/BitTorrent/DHT/Query.hs11
-rw-r--r--src/Network/BitTorrent/DHT/Session.hs3
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
92import Data.Typeable 92import Data.Typeable
93import Network 93import Network
94import Network.KRPC 94import Network.KRPC
95import Data.Maybe
95 96
96import Data.Torrent 97import Data.Torrent
97import Network.BitTorrent.Address 98import Network.BitTorrent.Address
@@ -105,11 +106,16 @@ import Network.KRPC ()
105node_id_key :: BKey 106node_id_key :: BKey
106node_id_key = "id" 107node_id_key = "id"
107 108
109read_only_key :: BKey
110read_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.
110data Query a = Query 115data 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
115instance BEncode a => BEncode (Query a) where 121instance 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
135instance BEncode a => BEncode (Response a) where 143instance 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
69nodeHandler :: Address ip => KRPC (Query a) (Response b) 69nodeHandler :: 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
71nodeHandler action = handler $ \ sockAddr (Query remoteId q) -> do 71nodeHandler 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
125findNodeQ :: Address ip => TableKey key => key -> Iteration ip NodeInfo 129findNodeQ :: Address ip => TableKey key => key -> Iteration ip NodeInfo
126findNodeQ key NodeInfo {..} = do 130findNodeQ 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
130getPeersQ :: Address ip => InfoHash -> Iteration ip PeerAddr 135getPeersQ :: 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
157search :: TableKey k => Address ip => k -> Iteration ip o -> Search ip o 162search :: TableKey k => Address ip => k -> Iteration ip o -> Search ip o
158search k action = do 163search _ 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)
493queryNode addr q = do 493queryNode 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