summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/dhtd.hs64
1 files changed, 52 insertions, 12 deletions
diff --git a/examples/dhtd.hs b/examples/dhtd.hs
index 755a65d7..badea2b1 100644
--- a/examples/dhtd.hs
+++ b/examples/dhtd.hs
@@ -98,13 +98,21 @@ showColumns rows = do
98marshalForClient :: String -> String 98marshalForClient :: String -> String
99marshalForClient s = show (length s) ++ ":" ++ s 99marshalForClient s = show (length s) ++ ":" ++ s
100 100
101data ClientHandle = ClientHandle Handle (MVar Int)
102
101-- | Writes a message and signals ready for next command. 103-- | Writes a message and signals ready for next command.
102hPutClient :: Handle -> String -> IO () 104hPutClient :: ClientHandle -> String -> IO ()
103hPutClient h s = hPutStr h ('.' : marshalForClient s) 105hPutClient (ClientHandle h hstate) s = do
106 st <- takeMVar hstate
107 hPutStr h ('.' : marshalForClient s)
108 putMVar hstate 1 -- ready for input
104 109
105-- | Writes message, but signals there is more to come. 110-- | Writes message, but signals there is more to come.
106hPutClientChunk :: Handle -> String -> IO () 111hPutClientChunk :: ClientHandle -> String -> IO ()
107hPutClientChunk h s = hPutStr h (' ' : marshalForClient s) 112hPutClientChunk (ClientHandle h hstate) s = do
113 st <- takeMVar hstate
114 hPutStr h (' ' : marshalForClient s)
115 putMVar hstate 2 -- ready for more output
108 116
109data DHTQuery nid ni = forall addr r tok. 117data DHTQuery nid ni = forall addr r tok.
110 ( Ord addr 118 ( Ord addr
@@ -253,7 +261,7 @@ reportResult ::
253 -> (r -> String) 261 -> (r -> String)
254 -> (tok -> Maybe String) 262 -> (tok -> Maybe String)
255 -> (ni -> String) 263 -> (ni -> String)
256 -> Handle 264 -> ClientHandle
257 -> Either String ([ni],[r],Maybe tok) 265 -> Either String ([ni],[r],Maybe tok)
258 -> IO () 266 -> IO ()
259reportResult meth showR showTok showN h (Left e) = hPutClient h e 267reportResult meth showR showTok showN h (Left e) = hPutClient h e
@@ -334,7 +342,7 @@ forkSearch method nid DHTQuery{qsearch,qshowTok,qshowR} dhtSearches dhtBuckets
334 writeTVar kvar $ Just $ searchLoop qsearch nid storeResult st 342 writeTVar kvar $ Just $ searchLoop qsearch nid storeResult st
335 343
336reportSearchResults :: (Show t, Ord t1, Ord t, Hashable t) => 344reportSearchResults :: (Show t, Ord t1, Ord t, Hashable t) =>
337 String -> Handle -> DHTSearch t1 t -> IO () 345 String -> ClientHandle -> DHTSearch t1 t -> IO ()
338reportSearchResults meth h DHTSearch{searchShowTok,searchState,searchResults} = do 346reportSearchResults meth h DHTSearch{searchShowTok,searchState,searchResults} = do
339 (ns,rs) <- atomically $ do 347 (ns,rs) <- atomically $ do
340 mm <- readTVar $ searchInformant searchState 348 mm <- readTVar $ searchInformant searchState
@@ -361,12 +369,39 @@ data Session = Session
361 , signalQuit :: MVar () 369 , signalQuit :: MVar ()
362 } 370 }
363 371
364clientSession :: Session -> t1 -> t -> Handle -> IO () 372exceptionsToClient :: ClientHandle -> IO () -> IO ()
373exceptionsToClient (ClientHandle h hstate) action =
374 action `catch` \(SomeException e) -> do
375 st <- takeMVar hstate
376 when (st /= 1) $ do
377 hPutStr h ('.': marshalForClient (show e))
378 putMVar hstate 1 -- ready for input
379
380hGetClientLine :: ClientHandle -> IO String
381hGetClientLine (ClientHandle h hstate) = do
382 st <- takeMVar hstate
383 -- st should be 1
384 x <- hGetLine h
385 putMVar hstate 0 -- ready for output
386 return x
387
388hCloseClient :: ClientHandle -> IO ()
389hCloseClient (ClientHandle h hstate) = do
390 st <- takeMVar hstate
391 hClose h
392 putMVar hstate 3 -- closed file handle
393
394clientSession0 :: Session -> t1 -> t -> Handle -> IO ()
395clientSession0 s sock cnum h = do
396 hstate <- newMVar 1 -- ready for input
397 clientSession s sock cnum (ClientHandle h hstate)
398
399clientSession :: Session -> t1 -> t -> ClientHandle -> IO ()
365clientSession s@Session{..} sock cnum h = do 400clientSession s@Session{..} sock cnum h = do
366 line <- dropWhile isSpace <$> hGetLine h 401 line <- dropWhile isSpace <$> hGetClientLine h
367 let (c,args) = second (dropWhile isSpace) $ break isSpace line 402 let (c,args) = second (dropWhile isSpace) $ break isSpace line
368 cmd0 :: IO () -> IO () 403 cmd0 :: IO () -> IO ()
369 cmd0 action = action >> clientSession s sock cnum h 404 cmd0 action = exceptionsToClient h action >> clientSession s sock cnum h
370 switchNetwork dest = do hPutClient h ("Network: "++dest) 405 switchNetwork dest = do hPutClient h ("Network: "++dest)
371 clientSession s{netname=dest} sock cnum h 406 clientSession s{netname=dest} sock cnum h
372 strp = B.unpack . fst . until snd dropEnd . (,False) . B.dropWhile isSpace . B.pack 407 strp = B.unpack . fst . until snd dropEnd . (,False) . B.dropWhile isSpace . B.pack
@@ -401,6 +436,7 @@ clientSession s@Session{..} sock cnum h = do
401 , ["toxids"] 436 , ["toxids"]
402 , ["c"] 437 , ["c"]
403 , ["help"] 438 , ["help"]
439 , ["throw"]
404 ] 440 ]
405 case (map toLower c,args) of 441 case (map toLower c,args) of
406 (n, _) | n `elem` Map.keys dhts -> switchNetwork n 442 (n, _) | n `elem` Map.keys dhts -> switchNetwork n
@@ -421,10 +457,14 @@ clientSession s@Session{..} sock cnum h = do
421 hPutClient h $ "error." 457 hPutClient h $ "error."
422 458
423 ("stop", _) -> do hPutClient h "Terminating DHT Daemon." 459 ("stop", _) -> do hPutClient h "Terminating DHT Daemon."
424 hClose h 460 hCloseClient h
425 putMVar signalQuit () 461 putMVar signalQuit ()
426 462
427 ("quit", _) -> hPutClient h "" >> hClose h 463 ("throw", er) -> cmd0 $ do
464 throwIO $ userError er
465 hPutClient h "The impossible happened!"
466
467 ("quit", _) -> hPutClient h "" >> hCloseClient h
428 468
429 ("pid", _) -> cmd0 $ do 469 ("pid", _) -> cmd0 $ do
430 pid <- getProcessID 470 pid <- getProcessID
@@ -1131,7 +1171,7 @@ main = do
1131 (toxids,rstr) <- fromMaybe ((,) <$> atomically (newTVar []) <*> newRoster) $ do 1171 (toxids,rstr) <- fromMaybe ((,) <$> atomically (newTVar []) <*> newRoster) $ do
1132 tox <- mbtox 1172 tox <- mbtox
1133 return $ return ( userKeys (Tox.toxCryptoKeys tox), Tox.toxRoster tox ) 1173 return $ return ( userKeys (Tox.toxCryptoKeys tox), Tox.toxRoster tox )
1134 let session = clientSession $ Session 1174 let session = clientSession0 $ Session
1135 { netname = concat $ take 1 $ Map.keys dhts -- initial default DHT 1175 { netname = concat $ take 1 $ Map.keys dhts -- initial default DHT
1136 , dhts = dhts -- all DHTs 1176 , dhts = dhts -- all DHTs
1137 , signalQuit = signalQuit 1177 , signalQuit = signalQuit