The Close List and the Search Entries are termed the \texttt{Node Lists} of the DHT State. \begin{code} module Network.Tox.DHT.NodeList where import Control.Applicative (Applicative, Const (..), getConst) import Control.Monad (guard) import Data.Maybe (listToMaybe) import Data.Monoid (Dual (..), Endo (..), Monoid, appEndo, getDual, mempty) import Network.Tox.Crypto.Key (PublicKey) import Network.Tox.DHT.ClientList (ClientList) import qualified Network.Tox.DHT.ClientList as ClientList import Network.Tox.DHT.Distance (Distance) import Network.Tox.DHT.KBuckets (KBuckets) import qualified Network.Tox.DHT.KBuckets as KBuckets import Network.Tox.NodeInfo.NodeInfo (NodeInfo) import Network.Tox.Time (Timestamp) class NodeList l where addNode :: Timestamp -> NodeInfo -> l -> l removeNode :: PublicKey -> l -> l viable :: NodeInfo -> l -> Bool baseKey :: l -> PublicKey traverseClientLists :: Applicative f => (ClientList -> f ClientList) -> l -> f l -- | 'closeNodes pub' returns the (pub',node) pairs of the Node List in -- increasing order of distance of pub' from pub. closeNodes :: PublicKey -> l -> [(Distance, NodeInfo)] -- | copied from Data.Traversable.foldMapDefault foldMapClientLists :: Monoid m => (ClientList -> m) -> l -> m foldMapClientLists f = getConst . traverseClientLists (Const . f) -- | copied from Data.Foldable.foldl foldlClientLists :: (a -> ClientList -> a) -> a -> l -> a foldlClientLists f z t = appEndo (getDual (foldMapClientLists (Dual . Endo . flip f) t)) z nodeListList :: l -> [NodeInfo] nodeListList = foldMapClientLists ClientList.nodeInfos foldNodes :: (a -> NodeInfo -> a) -> a -> l -> a foldNodes = foldlClientLists . ClientList.foldNodes lookupPublicKey :: PublicKey -> l -> Maybe NodeInfo lookupPublicKey publicKey list = do (dist,node) <- listToMaybe $ closeNodes publicKey list guard (dist == mempty) Just node instance NodeList ClientList where addNode = ClientList.addNode removeNode = ClientList.removeNode viable = ClientList.viable baseKey = ClientList.baseKey traverseClientLists = id closeNodes = ClientList.closeNodes instance NodeList KBuckets where addNode = KBuckets.addNode removeNode = KBuckets.removeNode viable = KBuckets.viable baseKey = KBuckets.baseKey traverseClientLists = KBuckets.traverseClientLists closeNodes = KBuckets.closeNodes \end{code}