{-# LANGUAGE ExistentialQuantification #-} module Network.Kademlia.CommonAPI ( module Network.Kademlia.CommonAPI , refreshBuckets ) where import Control.Concurrent import Control.Concurrent.STM import Data.Aeson as J (FromJSON, ToJSON) import Data.Hashable import qualified Data.Map as Map import Data.Serialize as S import qualified Data.Set as Set import Data.Time.Clock.POSIX import Data.Typeable import Network.Kademlia.Bootstrap import Network.Kademlia.Search import Network.Kademlia.Routing as R import Crypto.Tox (SecretKey,PublicKey) data DHT = forall nid ni qk. ( Show ni , Read ni , ToJSON ni , FromJSON ni , Ord ni , Hashable ni , Show nid , Ord nid , Hashable nid , Typeable ni , S.Serialize nid , Ord qk ) => DHT { dhtBuckets :: BucketRefresher nid ni qk , dhtSecretKey :: STM (Maybe SecretKey) , dhtPing :: Map.Map String (DHTPing ni) , dhtQuery :: Map.Map String (DHTQuery nid ni) , dhtAnnouncables :: Map.Map String (DHTAnnouncable nid) , dhtParseId :: String -> Either String nid , dhtSearches :: TVar (Map.Map (String,nid) (DHTSearch nid ni)) , dhtFallbackNodes :: IO [ni] , dhtBootstrap :: [ni] -> [ni] -> IO () , dhtShowHexId :: Maybe (nid -> String) } data DHTQuery nid ni = forall addr r tok qk. ( Ord addr , Typeable r , Typeable tok , Typeable ni , Ord qk ) => DHTQuery { qsearch :: Search nid addr tok ni r qk , qhandler :: ni -> nid -> IO ([ni], [r], Maybe tok) -- ^ Invoked on local node, when there is no query destination. , qshowR :: r -> String , qshowTok :: tok -> Maybe String } data DHTAnnouncable nid = forall dta tok ni r. ( Show r , Typeable dta -- information being announced , Typeable tok -- token , Typeable r -- search result , Typeable ni -- node ) => DHTAnnouncable { announceParseData :: String -> Either String dta , announceParseToken :: dta -> String -> Either String tok , announceParseAddress :: String -> Either String ni , announceSendData :: Either ( String {- search name -} , String -> Either String r , PublicKey {- me -} -> dta -> r -> IO ()) (dta -> tok -> Maybe ni -> IO (Maybe r)) , announceInterval :: POSIXTime , announceTarget :: dta -> nid } data DHTSearch nid ni = forall addr tok r qk. DHTSearch { searchThread :: ThreadId , searchState :: SearchState nid addr tok ni r qk , searchShowTok :: tok -> Maybe String , searchResults :: TVar (Set.Set String) } data DHTPing ni = forall r. DHTPing { pingQuery :: [String] -> ni -> IO (Maybe r) , pingShowResult :: r -> String }