module Main where import Control.Concurrent import Control.Concurrent.Async import Control.Concurrent.STM import Control.Concurrent.STM.TVar import Control.Exception import Data.Either import Data.IP (IPv6, toHostAddress6) import System.Environment import Hash2Pub.FediChord main :: IO () main = do -- ToDo: parse and pass config -- probably use `tomland` for that conf <- readConfig -- TODO: first initialise 'RealNode', then the vservers -- ToDo: load persisted caches, bootstrapping nodes … (serverSock, thisNode) <- fediChordInit conf -- currently no masking is necessary, as there is nothing to clean up cacheWriterThread <- forkIO $ cacheWriter thisNode thisNodeSnap <- readTVarIO thisNode realNode <- readTVarIO $ parentRealNode thisNodeSnap -- try joining the DHT using one of the provided bootstrapping nodes let tryJoining (bn:bns) = do j <- fediChordBootstrapJoin thisNode bn case j of Left err -> putStrLn ("join error: " <> err) >> tryJoining bns Right joined -> pure $ Right joined tryJoining [] = pure $ Left "Exhausted all bootstrap points for joining." joinedState <- tryJoining $ bootstrapNodes realNode either (\err -> do -- handle unsuccessful join putStrLn $ err <> " Error joining, start listening for incoming requests anyways" print =<< readTVarIO thisNode -- launch thread attempting to join on new cache entries _ <- forkIO $ joinOnNewEntriesThread thisNode wait =<< async (fediMainThreads serverSock thisNode) ) (\joinedNS -> do -- launch main eventloop with successfully joined state putStrLn "successful join" wait =<< async (fediMainThreads serverSock thisNode) ) joinedState pure () readConfig :: IO FediChordConf readConfig = do confDomainString : ipString : portString : bootstrapHost : bootstrapPortString : _ <- getArgs pure $ FediChordConf { confDomain = confDomainString , confIP = toHostAddress6 . read $ ipString , confDhtPort = read portString , confBootstrapNodes = [(bootstrapHost, read bootstrapPortString)] --, confStabiliseInterval = 60 }