{-# LANGUAGE NamedFieldPuns #-}

-- | One stop shop for configuring diffusion layer for upstream clients
-- nb. the module Ouroboros.Network.Diffusion.Governor should be imported qualified as PeerSelection by convention to aid comprehension

module Ouroboros.Network.Diffusion.Configuration
  ( defaultAcceptedConnectionsLimit
  , defaultPeerSharing
  , defaultDeadlineTargets
  , defaultDeadlineChurnInterval
  , defaultBulkChurnInterval
  , BlockProducerOrRelay (..)
    -- re-exports
  , AcceptedConnectionsLimit (..)
  , DiffusionMode (..)
  , PeerSelectionTargets (..)
  , PeerSharing (..)
  , defaultEgressPollInterval
  , defaultMuxCountersInterval
  , deactivateTimeout
  , closeConnectionTimeout
  , peerMetricsConfiguration
  , defaultTimeWaitTimeout
  , defaultProtocolIdleTimeout
  , defaultResetTimeout
  , handshake_QUERY_SHUTDOWN_DELAY
  , ps_POLICY_PEER_SHARE_STICKY_TIME
  , ps_POLICY_PEER_SHARE_MAX_PEERS
  , local_PROTOCOL_IDLE_TIMEOUT
  , local_TIME_WAIT_TIMEOUT
  ) where

import Control.Monad.Class.MonadTime.SI

import Network.Mux qualified as Mx

import Ouroboros.Network.ConnectionManager.Core (defaultProtocolIdleTimeout,
           defaultResetTimeout, defaultTimeWaitTimeout)
import Ouroboros.Network.Diffusion.Policies (closeConnectionTimeout,
           deactivateTimeout, peerMetricsConfiguration)
import Ouroboros.Network.DiffusionMode
import Ouroboros.Network.PeerSelection.Governor.Types
           (PeerSelectionTargets (..))
import Ouroboros.Network.PeerSelection.PeerSharing (PeerSharing (..))
import Ouroboros.Network.PeerSharing (ps_POLICY_PEER_SHARE_MAX_PEERS,
           ps_POLICY_PEER_SHARE_STICKY_TIME)
import Ouroboros.Network.Protocol.Handshake (handshake_QUERY_SHUTDOWN_DELAY)
import Ouroboros.Network.Server.RateLimiting (AcceptedConnectionsLimit (..))

-- | Outbound governor targets
-- Targets may vary depending on whether a node is operating in
-- Genesis mode.


-- | A Boolean like type to differentiate between a node which is configured as
-- a block producer and a relay.  Some default options depend on that value.
--
data BlockProducerOrRelay = BlockProducer | Relay
  deriving Int -> BlockProducerOrRelay -> ShowS
[BlockProducerOrRelay] -> ShowS
BlockProducerOrRelay -> String
(Int -> BlockProducerOrRelay -> ShowS)
-> (BlockProducerOrRelay -> String)
-> ([BlockProducerOrRelay] -> ShowS)
-> Show BlockProducerOrRelay
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BlockProducerOrRelay -> ShowS
showsPrec :: Int -> BlockProducerOrRelay -> ShowS
$cshow :: BlockProducerOrRelay -> String
show :: BlockProducerOrRelay -> String
$cshowList :: [BlockProducerOrRelay] -> ShowS
showList :: [BlockProducerOrRelay] -> ShowS
Show


-- | Default peer targets in Praos mode
--
defaultDeadlineTargets :: BlockProducerOrRelay
                       -- ^ block producer or relay node
                       -> PeerSelectionTargets
defaultDeadlineTargets :: BlockProducerOrRelay -> PeerSelectionTargets
defaultDeadlineTargets BlockProducerOrRelay
bp =
  PeerSelectionTargets {
    targetNumberOfRootPeers :: Int
targetNumberOfRootPeers                 = case BlockProducerOrRelay
bp of { BlockProducerOrRelay
BlockProducer -> Int
100; BlockProducerOrRelay
Relay -> Int
60  },
    targetNumberOfKnownPeers :: Int
targetNumberOfKnownPeers                = case BlockProducerOrRelay
bp of { BlockProducerOrRelay
BlockProducer -> Int
100; BlockProducerOrRelay
Relay -> Int
150 },
    targetNumberOfEstablishedPeers :: Int
targetNumberOfEstablishedPeers          = Int
30,
    targetNumberOfActivePeers :: Int
targetNumberOfActivePeers               = Int
20,
    targetNumberOfKnownBigLedgerPeers :: Int
targetNumberOfKnownBigLedgerPeers       = Int
15,
    targetNumberOfEstablishedBigLedgerPeers :: Int
targetNumberOfEstablishedBigLedgerPeers = Int
10,
    targetNumberOfActiveBigLedgerPeers :: Int
targetNumberOfActiveBigLedgerPeers      = Int
5 }

-- | Inbound governor targets
--
defaultAcceptedConnectionsLimit :: AcceptedConnectionsLimit
defaultAcceptedConnectionsLimit :: AcceptedConnectionsLimit
defaultAcceptedConnectionsLimit =
  AcceptedConnectionsLimit {
    acceptedConnectionsHardLimit :: Word32
acceptedConnectionsHardLimit = Word32
512,
    acceptedConnectionsSoftLimit :: Word32
acceptedConnectionsSoftLimit = Word32
384,
    acceptedConnectionsDelay :: DiffTime
acceptedConnectionsDelay     = DiffTime
5 }

-- | Node's peer sharing participation flag
--
defaultPeerSharing :: BlockProducerOrRelay
                   -> PeerSharing
defaultPeerSharing :: BlockProducerOrRelay -> PeerSharing
defaultPeerSharing BlockProducerOrRelay
BlockProducer = PeerSharing
PeerSharingDisabled
defaultPeerSharing BlockProducerOrRelay
Relay         = PeerSharing
PeerSharingEnabled

defaultDeadlineChurnInterval :: DiffTime
defaultDeadlineChurnInterval :: DiffTime
defaultDeadlineChurnInterval = DiffTime
3300

defaultBulkChurnInterval :: DiffTime
defaultBulkChurnInterval :: DiffTime
defaultBulkChurnInterval = DiffTime
900

--
-- Constants
--

-- | Protocol inactivity timeout for local (e.g. /node-to-client/) connections.
--
local_PROTOCOL_IDLE_TIMEOUT :: DiffTime
local_PROTOCOL_IDLE_TIMEOUT :: DiffTime
local_PROTOCOL_IDLE_TIMEOUT = DiffTime
2 -- 2 seconds

-- | Used to set 'timeWaitTimeout' for local (e.g. /node-to-client/) connections.
--
local_TIME_WAIT_TIMEOUT :: DiffTime
local_TIME_WAIT_TIMEOUT :: DiffTime
local_TIME_WAIT_TIMEOUT = DiffTime
0

-- | Mux egress queue polling
-- for tuning latency vs. network efficiency
defaultEgressPollInterval :: DiffTime
defaultEgressPollInterval :: DiffTime
defaultEgressPollInterval = DiffTime
0

-- | How often diffusion traces its mux counters, see
-- 'Ouroboros.Network.Diffusion.Types.dcMuxCountersInterval'; zero keeps none.
defaultMuxCountersInterval :: DiffTime
defaultMuxCountersInterval :: DiffTime
defaultMuxCountersInterval = DiffTime
Mx.countersInterval