summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-11-18 22:42:24 -0500
committerjoe <joe@jerkface.net>2017-11-18 22:42:24 -0500
commitbacefe39096c2c39afb6af7f01e729233a47522d (patch)
tree23ea204fde593d3d7062fd9fb6bb9327297f95ae
parent5191d7c488462afd4d97e46865b83e939552c4dd (diff)
New cli "c" interface to Connection.Manager.
-rw-r--r--Connection.hs6
-rw-r--r--examples/dhtd.hs136
2 files changed, 56 insertions, 86 deletions
diff --git a/Connection.hs b/Connection.hs
index 22c5b1da..3287bc1b 100644
--- a/Connection.hs
+++ b/Connection.hs
@@ -35,6 +35,12 @@ data Manager status k = Manager
35 , showKey :: k -> String 35 , showKey :: k -> String
36 } 36 }
37 37
38showStatus :: Manager status k -> Status status -> String
39showStatus mgr Dormant = "dormant"
40showStatus mgr Established = "established"
41showStatus mgr (InProgress s) = "in progress ("++showProgress mgr s++")"
42
43
38addManagers :: (Ord kA, Ord kB) => 44addManagers :: (Ord kA, Ord kB) =>
39 Manager statusA kA 45 Manager statusA kA
40 -> Manager statusB kB 46 -> Manager statusB kB
diff --git a/examples/dhtd.hs b/examples/dhtd.hs
index abf0c297..219221e5 100644
--- a/examples/dhtd.hs
+++ b/examples/dhtd.hs
@@ -23,7 +23,6 @@ import Control.Applicative
23import Control.Concurrent.STM 23import Control.Concurrent.STM
24import Control.Exception 24import Control.Exception
25import Control.Monad 25import Control.Monad
26import Control.Monad.IO.Class (liftIO)
27import Control.Monad.Trans.Resource (runResourceT) 26import Control.Monad.Trans.Resource (runResourceT)
28import Data.Bool 27import Data.Bool
29import Data.Char 28import Data.Char
@@ -73,6 +72,7 @@ import qualified Data.Aeson as J
73import qualified Data.ByteString.Lazy as L 72import qualified Data.ByteString.Lazy as L
74import qualified Data.ByteString.Char8 as B 73import qualified Data.ByteString.Char8 as B
75import Control.Concurrent.Tasks 74import Control.Concurrent.Tasks
75import Control.Monad.Trans.Control
76import System.IO.Error 76import System.IO.Error
77import qualified Data.Serialize as S 77import qualified Data.Serialize as S
78import Network.BitTorrent.DHT.ContactInfo as Peers 78import Network.BitTorrent.DHT.ContactInfo as Peers
@@ -94,6 +94,7 @@ import OnionRouter
94import ConsoleWriter 94import ConsoleWriter
95import Presence 95import Presence
96import XMPPServer 96import XMPPServer
97import Connection
97 98
98 99
99showReport :: [(String,String)] -> String 100showReport :: [(String,String)] -> String
@@ -154,21 +155,6 @@ data DHTAnnouncable nid = forall dta tok ni r.
154 , qresultAddr :: dta -> nid 155 , qresultAddr :: dta -> nid
155 } 156 }
156 157
157data DHTLink = forall status linkid params.
158 ( Show status
159 , Show linkid
160 , Typeable status
161 , Typeable linkid
162 , Typeable params
163 ) => DHTLink
164 { linkInit :: params -> IO (Either String status)
165 , linkParamParser :: [String] -> Either String params
166 , linkStatus :: IO (Either String status)
167 , showLinkStatus :: status -> String
168 , linkNewPipe :: String -> linkid -> IO (Either String status)
169 , linkUnPipe :: linkid -> IO (Either String status)
170 }
171
172data DHTSearch nid ni = forall addr tok r. DHTSearch 158data DHTSearch nid ni = forall addr tok r. DHTSearch
173 { searchThread :: ThreadId 159 { searchThread :: ThreadId
174 , searchState :: SearchState nid addr tok ni r 160 , searchState :: SearchState nid addr tok ni r
@@ -199,7 +185,6 @@ data DHT = forall nid ni. ( Show ni
199 , dhtPing :: Map.Map String (DHTPing ni) 185 , dhtPing :: Map.Map String (DHTPing ni)
200 , dhtQuery :: Map.Map String (DHTQuery nid ni) 186 , dhtQuery :: Map.Map String (DHTQuery nid ni)
201 , dhtAnnouncables :: Map.Map String (DHTAnnouncable nid) 187 , dhtAnnouncables :: Map.Map String (DHTAnnouncable nid)
202 , dhtLinks :: Map.Map String DHTLink
203 , dhtParseId :: String -> Either String nid 188 , dhtParseId :: String -> Either String nid
204 , dhtSearches :: TVar (Map.Map (String,nid) (DHTSearch nid ni)) 189 , dhtSearches :: TVar (Map.Map (String,nid) (DHTSearch nid ni))
205 , dhtFallbackNodes :: IO [ni] 190 , dhtFallbackNodes :: IO [ni]
@@ -383,6 +368,8 @@ reportSearchResults meth h DHTSearch{searchShowTok,searchState,searchResults} =
383 ns' = map showN ns 368 ns' = map showN ns
384 reportResult meth id (const Nothing) id h (Right (ns',rs, Just ())) 369 reportResult meth id (const Nothing) id h (Right (ns',rs, Just ()))
385 370
371data ConnectionManager = forall status k. ConnectionManager { typedManager :: Connection.Manager status k }
372
386data Session = Session 373data Session = Session
387 { netname :: String 374 { netname :: String
388 , dhts :: Map.Map String DHT 375 , dhts :: Map.Map String DHT
@@ -392,6 +379,7 @@ data Session = Session
392 , toxkeys :: TVar Tox.AnnouncedKeys 379 , toxkeys :: TVar Tox.AnnouncedKeys
393 , userkeys :: TVar [(SecretKey,PublicKey)] 380 , userkeys :: TVar [(SecretKey,PublicKey)]
394 , roster :: Roster 381 , roster :: Roster
382 , connectionManager :: ConnectionManager
395 , onionRouter :: OnionRouter 383 , onionRouter :: OnionRouter
396 , announcer :: Announcer 384 , announcer :: Announcer
397 , signalQuit :: IO () 385 , signalQuit :: IO ()
@@ -641,7 +629,6 @@ clientSession s@Session{..} sock cnum h = do
641 hPutClientChunk h $ "trampolines: " ++ show (IntMap.size ts) ++ "\n" 629 hPutClientChunk h $ "trampolines: " ++ show (IntMap.size ts) ++ "\n"
642 hPutClient h $ showColumns $ ["","responses","timeouts"]:r 630 hPutClient h $ showColumns $ ["","responses","timeouts"]:r
643 631
644
645 ("g", s) | Just DHT{..} <- Map.lookup netname dhts 632 ("g", s) | Just DHT{..} <- Map.lookup netname dhts
646 -> cmd0 $ do 633 -> cmd0 $ do
647 -- arguments: method 634 -- arguments: method
@@ -909,46 +896,29 @@ clientSession s@Session{..} sock cnum h = do
909 mkentry (k :-> Down tm) = [ show cnt, show k, show (now - tm) ] 896 mkentry (k :-> Down tm) = [ show cnt, show k, show (now - tm) ]
910 where Just (_,(cnt,_)) = MM.lookup' k (Tox.keyAssoc keydb) 897 where Just (_,(cnt,_)) = MM.lookup' k (Tox.keyAssoc keydb)
911 hPutClient h $ showColumns entries 898 hPutClient h $ showColumns entries
912 ("c", s) | "" <- strp s -> cmd0 $ do 899
913 let combinedLinkMap = Map.unions $map (dhtLinks . snd) (Map.toList dhts) 900 ("c", s) | "" <- strp s -> cmd0 $ join $ atomically $ do
914 -- TODO: list all connections 901 ConnectionManager mgr <- return connectionManager
915 let connections = [[{-TODO-}]] 902 cmap <- connections mgr
916 hPutClient h $ showColumns connections 903 cs <- Map.toList <$> mapM connStatus cmap
917 ("c", s) -> cmd0 $ do 904 let mkrow = Connection.showKey mgr *** Connection.showStatus mgr
918 let combinedLinkMap = Map.unions $map (dhtLinks . snd) (Map.toList dhts) 905 rs = map mkrow cs
919 -- form new connection according of type corresponding to parameter 906 return $ do
920 let ws = words s 907 hPutClient h $ showReport rs
921 result
922 <- case ws of
923 (linktype:rest)
924 -> case (Map.lookup (head ws) combinedLinkMap) of
925 Nothing -> return . Left $ "I don't know a '" ++ head ws ++ "' link type."
926 Just l@(DHTLink
927 { linkInit {- :: params -> IO (Either String status) -}
928 , linkParamParser {- :: [String] -> Either String params -}
929 , showLinkStatus {- :: status -> String -}
930 }) -> case linkParamParser rest of
931 Left er -> return $ Left er
932 Right params -> fmap showLinkStatus <$> linkInit params
933 _ -> return $ Left "parse error"
934 case result of
935 Left er -> hPutClient h er
936 Right statusstr -> hPutClient h statusstr
937 908
938 ("help", s) | Just DHT{..} <- Map.lookup netname dhts 909 ("help", s) | Just DHT{..} <- Map.lookup netname dhts
939 -> cmd0 $ do 910 -> cmd0 $ do
940 let tolist :: a -> [a] 911 let tolist :: a -> [a]
941 tolist = (:[]) 912 tolist = (:[])
942 913
943 dhtkeys, announcables, links, ks, allcommands :: [[String]] 914 dhtkeys, announcables, ks, allcommands :: [[String]]
944 dhtkeys = map tolist $ Map.keys dhts 915 dhtkeys = map tolist $ Map.keys dhts
945 queries = map (tolist . ("s "++)) $ Map.keys dhtQuery 916 queries = map (tolist . ("s "++)) $ Map.keys dhtQuery
946 xs = map (tolist . ("x "++)) $ Map.keys dhtQuery 917 xs = map (tolist . ("x "++)) $ Map.keys dhtQuery
947 gs = map (tolist . ("g "++)) $ Map.keys dhtQuery 918 gs = map (tolist . ("g "++)) $ Map.keys dhtQuery
948 announcables = map (tolist . ("p "++)) $ Map.keys dhtAnnouncables 919 announcables = map (tolist . ("p "++)) $ Map.keys dhtAnnouncables
949 links = map (tolist . ("c "++)) $ Map.keys dhtLinks
950 ks = [["k gen"],["k public"],["k secret"]] 920 ks = [["k gen"],["k public"],["k secret"]]
951 allcommands = sortBy (comparing head) $ concat [sessionCommands, dhtkeys, announcables, links, ks, queries, gs,xs] 921 allcommands = sortBy (comparing (take 1)) $ concat [sessionCommands, dhtkeys, announcables, ks, queries, gs,xs]
952 922
953 hPutClient h ("Available commands:\n" ++ showColumns allcommands) 923 hPutClient h ("Available commands:\n" ++ showColumns allcommands)
954 924
@@ -1013,7 +983,7 @@ noArgPing f [] x = f x
1013noArgPing _ _ _ = return Nothing 983noArgPing _ _ _ = return Nothing
1014 984
1015main :: IO () 985main :: IO ()
1016main = do 986main = runResourceT $ liftBaseWith $ \resT -> do
1017 args <- getArgs 987 args <- getArgs
1018 let opts = parseArgs args sensibleDefaults 988 let opts = parseArgs args sensibleDefaults
1019 print opts 989 print opts
@@ -1027,6 +997,18 @@ main = do
1027 997
1028 announcer <- forkAnnouncer 998 announcer <- forkAnnouncer
1029 999
1000 -- XMPP initialization
1001 cw <- newConsoleWriter
1002 serverVar <- atomically $ newEmptyTMVar
1003 state <- newPresenceState cw serverVar
1004
1005 -- XMPP stanza handling
1006 sv <- resT $ xmppServer (presenceHooks state (verbosity opts))
1007 -- We now have a server object but it's not ready to use until
1008 -- we put it into the 'server' field of our /state/ record.
1009
1010 conns <- xmppConnections sv
1011
1030 (quitBt,btdhts,btips,baddrs) <- case portbt opts of 1012 (quitBt,btdhts,btips,baddrs) <- case portbt opts of
1031 "" -> return (return (), Map.empty,return [],[]) 1013 "" -> return (return (), Map.empty,return [],[])
1032 p -> do 1014 p -> do
@@ -1097,9 +1079,6 @@ main = do
1097 , qresultAddr = const $ Mainline.zeroID 1079 , qresultAddr = const $ Mainline.zeroID
1098 })] 1080 })]
1099 1081
1100 , dhtLinks = Map.fromList
1101 [ {- TODO -}
1102 ]
1103 , dhtSecretKey = return Nothing 1082 , dhtSecretKey = return Nothing
1104 , dhtBootstrap = case wantip of 1083 , dhtBootstrap = case wantip of
1105 Want_IP4 -> btBootstrap4 1084 Want_IP4 -> btBootstrap4
@@ -1279,9 +1258,6 @@ main = do
1279 1258
1280 , announceInterval = 8 1259 , announceInterval = 8
1281 })] 1260 })]
1282 , dhtLinks = Map.fromList
1283 [ {- TODO -}
1284 ]
1285 , dhtSecretKey = return $ Just $ transportSecret (Tox.toxCryptoKeys tox) 1261 , dhtSecretKey = return $ Just $ transportSecret (Tox.toxCryptoKeys tox)
1286 , dhtBootstrap = case wantip of 1262 , dhtBootstrap = case wantip of
1287 Want_IP4 -> toxStrap4 1263 Want_IP4 -> toxStrap4
@@ -1322,6 +1298,7 @@ main = do
1322 , toxkeys = keysdb 1298 , toxkeys = keysdb
1323 , userkeys = toxids 1299 , userkeys = toxids
1324 , roster = rstr 1300 , roster = rstr
1301 , connectionManager = ConnectionManager conns
1325 , onionRouter = orouter 1302 , onionRouter = orouter
1326 , externalAddresses = liftM2 (++) btips toxips 1303 , externalAddresses = liftM2 (++) btips toxips
1327 , announcer = announcer 1304 , announcer = announcer
@@ -1352,39 +1329,26 @@ main = do
1352 bootstrap btSaved fallbackNodes 1329 bootstrap btSaved fallbackNodes
1353 return () 1330 return ()
1354 1331
1355 -- XMPP initialization 1332 atomically $ do
1356 cw <- newConsoleWriter 1333 putTMVar serverVar (sv,conns) -- Okay, now it's ready. :)
1357 serverVar <- atomically $ newEmptyTMVar 1334 -- FIXME: This is error prone.
1358 state <- newPresenceState cw serverVar 1335
1359 1336 forkIO $ do
1360 -- XMPP stanza handling 1337 myThreadId >>= flip labelThread "XMPP.stanzas"
1361 runResourceT $ do 1338 let console = cwPresenceChan <$> consoleWriter state
1362 sv <- xmppServer (presenceHooks state (verbosity opts)) 1339 fix $ \loop -> do
1363 -- We now have a server object but it's not ready to use until 1340 what <- atomically
1364 -- we put it into the 'server' field of our /state/ record. 1341 $ orElse (do (client,stanza) <- maybe retry takeTMVar console
1365 1342 return $ do informClientPresence0 state Nothing client stanza
1366 liftIO $ do 1343 loop)
1367 conns <- xmppConnections sv 1344 (checkQuit >> return (return ()))
1368 atomically $ do 1345 what
1369 putTMVar serverVar (sv,conns) -- Okay, now it's ready. :) 1346
1370 -- FIXME: This is error prone. 1347 hPutStrLn stderr "Started XMPP server."
1371 1348
1372 forkIO $ do 1349 -- Wait for DHT and XMPP threads to finish.
1373 myThreadId >>= flip labelThread "XMPP.stanzas" 1350 -- Use ResourceT to clean-up XMPP server.
1374 let console = cwPresenceChan <$> consoleWriter state 1351 waitForSignal
1375 fix $ \loop -> do
1376 what <- atomically
1377 $ orElse (do (client,stanza) <- maybe retry takeTMVar console
1378 return $ do informClientPresence0 state Nothing client stanza
1379 loop)
1380 (checkQuit >> return (return ()))
1381 what
1382
1383 hPutStrLn stderr "Started XMPP server."
1384
1385 -- Wait for DHT and XMPP threads to finish.
1386 -- Use ResourceT to clean-up XMPP server.
1387 waitForSignal
1388 1352
1389 stopAnnouncer announcer 1353 stopAnnouncer announcer
1390 quitBt 1354 quitBt