hbs2/hbs2-peer/app/Bootstrap.hs

99 lines
3.2 KiB
Haskell

{-# Language AllowAmbiguousTypes #-}
{-# Language TypeOperators #-}
module Bootstrap where
import HBS2.Data.Types.Peer
import HBS2.Prelude
import HBS2.Net.Proto.Types
import HBS2.Net.Proto.Peer
import HBS2.Clock
import HBS2.Net.Proto.Sessions
import PeerConfig
import HBS2.System.Logger.Simple
import Network.DNS
import Control.Monad.Reader
import Data.ByteString.Char8 qualified as B8
import Data.Foldable
import Data.Maybe
import Data.Set qualified as Set
import Data.Set (Set)
import Control.Monad.Trans.Maybe
data PeerDnsBootStrapKey
data PeerKnownPeer
instance Monad m => HasCfgKey PeerDnsBootStrapKey (Set String) m where
key = "bootstrap-dns"
instance Monad m => HasCfgKey PeerKnownPeer (Set String) m where
key = "known-peer"
-- FIXME: tcp-addr-support-bootstrap
bootstrapDnsLoop :: forall e m . ( HasPeer e
, Request e (PeerHandshake e) m
, HasNonces (PeerHandshake e) m
, Nonce (PeerHandshake e) ~ PingNonce
, Sessions e (PeerHandshake e) m
, Pretty (Peer e)
-- , FromSockAddr 'UDP (Peer e)
, e ~ L4Proto
, MonadIO m
)
=> PeerConfig -> m ()
bootstrapDnsLoop (PeerConfig syn) = do
pause @'Seconds 2
rs <- liftIO $ makeResolvSeed defaultResolvConf
forever do
debug "I'm a bootstrapLoop"
dns <- runReaderT(cfgValue @PeerDnsBootStrapKey) syn
<&> (<> Set.singleton "bootstrap.hbs2.net")
-- FIXME: utf8-domains
for_ (Set.toList dns) $ \dn -> do
debug $ "bootstrapping from" <+> pretty dn
answers <- liftIO $ withResolver rs $ \resolver -> lookupTXT resolver (B8.pack dn) <&> either mempty id
void $ runMaybeT do
for_ answers $ \answ -> do
-- FIXME: tcp-addr-support-1
pa <- MaybeT $ pure $ fromStringMay @(PeerAddr L4Proto) (B8.unpack answ)
pip <- fromPeerAddr pa
debug $ "BOOTSTRAP:" <+> pretty pip
lift $ sendPing @e pip
-- FIXME: fix-bootstrapDnsLoop-time-hardcode
pause @'Seconds 300
-- FIXME: tcp-addr-support-known-peers-loop
knownPeersPingLoop :: forall e m . ( HasPeer e
, Request e (PeerHandshake e) m
, HasNonces (PeerHandshake e) m
, Nonce (PeerHandshake e) ~ PingNonce
, Sessions e (PeerHandshake e) m
, Pretty (Peer e)
, e ~ L4Proto
, MonadIO m)
=> PeerConfig -> m ()
knownPeersPingLoop (PeerConfig syn) = do
-- FIXME: add validation and error handling
-- FIXME: tcp-addr-support-2
let parseKnownPeers xs = do
let pa = foldMap (maybeToList . fromStringMay) xs
mapM fromPeerAddr pa
let them = runReader (cfgValue @PeerKnownPeer) syn & Set.toList
knownPeers' <- liftIO $ parseKnownPeers them
forever do
forM_ knownPeers' (sendPing @e)
pause @'Minutes 20