diff options
Diffstat (limited to 'examples')
-rw-r--r-- | examples/dht.hs | 17 | ||||
-rw-r--r-- | examples/dhtd.hs | 24 |
2 files changed, 31 insertions, 10 deletions
diff --git a/examples/dht.hs b/examples/dht.hs index feeee9ff..16b12678 100644 --- a/examples/dht.hs +++ b/examples/dht.hs | |||
@@ -1,6 +1,6 @@ | |||
1 | {-# LANGUAGE NondecreasingIndentation #-} | 1 | {-# LANGUAGE NondecreasingIndentation #-} |
2 | import Control.Monad | 2 | import Control.Monad |
3 | import Control.Monad.Fix | 3 | import Data.Function |
4 | import Control.Monad.IO.Class | 4 | import Control.Monad.IO.Class |
5 | import Data.Char | 5 | import Data.Char |
6 | import Network.Socket as Socket | 6 | import Network.Socket as Socket |
@@ -34,16 +34,21 @@ hReadInt h = do | |||
34 | -- and /.../ is the sequence of characters | 34 | -- and /.../ is the sequence of characters |
35 | -- | 35 | -- |
36 | -- Note: The first byte after the count is ignored and discarded. | 36 | -- Note: The first byte after the count is ignored and discarded. |
37 | readResponse :: Handle -> IO String | 37 | readResponse :: Handle -> IO (Char, String) |
38 | readResponse h = do | 38 | readResponse h = do |
39 | c <- hGetChar h | ||
39 | n <- hReadInt h | 40 | n <- hReadInt h |
40 | sequence $ replicate n (hGetChar h) | 41 | s <- sequence $ replicate n (hGetChar h) |
42 | return (c,s) | ||
41 | 43 | ||
42 | -- | Send a command to the dhtd daemon and then print the response. | 44 | -- | Send a command to the dhtd daemon and then print the response. |
43 | sendCommand :: Handle -> String -> InputT IO () | 45 | sendCommand :: Handle -> String -> InputT IO () |
44 | sendCommand h cmd = do resp <- liftIO $ do hPutStrLn h cmd | 46 | sendCommand h cmd = do liftIO $ hPutStrLn h cmd |
45 | readResponse h | 47 | fix $ \again -> do |
46 | outputStrLn resp | 48 | (c, resp) <- liftIO $ readResponse h |
49 | if c /= '.' | ||
50 | then outputStr resp >> again | ||
51 | else outputStrLn resp | ||
47 | 52 | ||
48 | -- | Get one line of input and send it to the daemon, then run the | 53 | -- | Get one line of input and send it to the daemon, then run the |
49 | -- passed continuation if it wasn't "quit". | 54 | -- passed continuation if it wasn't "quit". |
diff --git a/examples/dhtd.hs b/examples/dhtd.hs index 1b02a37a..68074e2b 100644 --- a/examples/dhtd.hs +++ b/examples/dhtd.hs | |||
@@ -33,6 +33,7 @@ import System.Mem | |||
33 | import Data.Torrent (InfoHash) | 33 | import Data.Torrent (InfoHash) |
34 | import Network.BitTorrent.Address | 34 | import Network.BitTorrent.Address |
35 | import Network.BitTorrent.DHT | 35 | import Network.BitTorrent.DHT |
36 | import Network.BitTorrent.DHT.Search | ||
36 | import Network.BitTorrent.DHT.Query | 37 | import Network.BitTorrent.DHT.Query |
37 | import Network.BitTorrent.DHT.Message (FindNode(..),NodeFound(..),GetPeers(..),GotPeers(..)) | 38 | import Network.BitTorrent.DHT.Message (FindNode(..),NodeFound(..),GetPeers(..),GotPeers(..)) |
38 | import Network.KRPC.Manager (QueryFailure(..)) | 39 | import Network.KRPC.Manager (QueryFailure(..)) |
@@ -49,6 +50,7 @@ import Data.Time.Clock | |||
49 | #else | 50 | #else |
50 | import Control.Concurrent | 51 | import Control.Concurrent |
51 | #endif | 52 | #endif |
53 | import Control.Concurrent.STM | ||
52 | import System.Environment | 54 | import System.Environment |
53 | 55 | ||
54 | mkNodeAddr :: SockAddr -> NodeAddr IPv4 | 56 | mkNodeAddr :: SockAddr -> NodeAddr IPv4 |
@@ -130,7 +132,10 @@ marshalForClient :: String -> String | |||
130 | marshalForClient s = show (length s) ++ ":" ++ s | 132 | marshalForClient s = show (length s) ++ ":" ++ s |
131 | 133 | ||
132 | hPutClient :: Handle -> String -> IO () | 134 | hPutClient :: Handle -> String -> IO () |
133 | hPutClient h s = hPutStr h (marshalForClient s) | 135 | hPutClient h s = hPutStr h ('.' : marshalForClient s) |
136 | |||
137 | hPutClientChunk :: Handle -> String -> IO () | ||
138 | hPutClientChunk h s = hPutStr h (' ' : marshalForClient s) | ||
134 | 139 | ||
135 | clientSession :: Node IPv4 -> MVar () -> RestrictedSocket -> Int -> Handle -> IO () | 140 | clientSession :: Node IPv4 -> MVar () -> RestrictedSocket -> Int -> Handle -> IO () |
136 | clientSession st signalQuit sock n h = do | 141 | clientSession st signalQuit sock n h = do |
@@ -280,9 +285,20 @@ clientSession st signalQuit sock n h = do | |||
280 | ("search-peers", s) -> cmd $ do | 285 | ("search-peers", s) -> cmd $ do |
281 | case readEither s of | 286 | case readEither s of |
282 | Right ih -> do | 287 | Right ih -> do |
283 | ps <- Set.toList <$> isearch ioGetPeers ih | 288 | (tid, s) <- isearch ioGetPeers ih |
284 | return $ do | 289 | flip fix Set.empty $ \again shown -> do |
285 | hPutClient h $ unlines $ map (show . pPrint) ps | 290 | (chk,fin) <- liftIO . atomically $ do |
291 | r <- (Set.\\ shown) <$> readTVar (searchResults s) | ||
292 | if not $ Set.null r | ||
293 | then (,) r <$> searchIsFinished s | ||
294 | else searchIsFinished s >>= check >> return (Set.empty,True) | ||
295 | let ps = case Set.toList chk of | ||
296 | [] -> "" | ||
297 | _ -> unlines $ map (show . pPrint) $ Set.toList chk | ||
298 | if fin then return $ hPutClient h ps | ||
299 | else do | ||
300 | liftIO $ hPutClientChunk h ps | ||
301 | again (shown `Set.union` chk) | ||
286 | Left er -> return $ hPutClient h er | 302 | Left er -> return $ hPutClient h er |
287 | 303 | ||
288 | _ -> cmd0 $ hPutClient h "error." | 304 | _ -> cmd0 $ hPutClient h "error." |