From 0682bf4bad0d59cf36958b58b00a5aa1c61f2236 Mon Sep 17 00:00:00 2001 From: Trolli Schmittlauch Date: Tue, 12 May 2020 21:24:56 +0200 Subject: [PATCH] create local server socket --- Hash2Pub/Hash2Pub.cabal | 4 +- Hash2Pub/src/Hash2Pub/DHTProtocol.hs | 3 +- Hash2Pub/src/Hash2Pub/FediChord.hs | 80 ++++++++++++++++++++-------- Hash2Pub/src/Hash2Pub/Main.hs | 3 +- 4 files changed, 64 insertions(+), 26 deletions(-) diff --git a/Hash2Pub/Hash2Pub.cabal b/Hash2Pub/Hash2Pub.cabal index 2774a4b..7792198 100644 --- a/Hash2Pub/Hash2Pub.cabal +++ b/Hash2Pub/Hash2Pub.cabal @@ -46,7 +46,7 @@ category: Network extra-source-files: CHANGELOG.md common deps - build-depends: base ^>=4.12.0.0, containers ^>=0.6.0.1, bytestring, utf8-string ^>=1.0.1.1, network ^>=2.8.0.1, time ^>=1.8.0.2, cmdargs ^>= 0.10, cryptonite ^>= 0.25, memory, async, asn1-encoding, asn1-types, asn1-parse, publicsuffix, network-byte-order, safe + build-depends: base ^>=4.12.0.0, containers ^>=0.6.0.1, bytestring, utf8-string ^>=1.0.1.1, network ^>=2.8.0.1, time ^>=1.8.0.2, cmdargs ^>= 0.10, cryptonite ^>= 0.25, memory, async, asn1-encoding, asn1-types, asn1-parse, publicsuffix, network-byte-order, safe, iproute ghc-options: -Wall @@ -74,7 +74,7 @@ executable Hash2Pub import: deps -- adding the library as a dependency - build-depends: Hash2Pub, iproute + build-depends: Hash2Pub -- .hs or .lhs file containing the Main module. main-is: Main.hs diff --git a/Hash2Pub/src/Hash2Pub/DHTProtocol.hs b/Hash2Pub/src/Hash2Pub/DHTProtocol.hs index 5953dab..b5fc77c 100644 --- a/Hash2Pub/src/Hash2Pub/DHTProtocol.hs +++ b/Hash2Pub/src/Hash2Pub/DHTProtocol.hs @@ -19,6 +19,8 @@ import Data.Maybe (maybe, fromMaybe) import qualified Data.Set as Set import qualified Data.Map as Map import Data.Time.Clock.POSIX +import Network.Socket hiding (send, sendTo, recv, recvFrom) +import Network.Socket.ByteString import Hash2Pub.FediChord ( NodeID @@ -187,4 +189,3 @@ deleteCacheEntry = Map.update modifier modifier (ProxyEntry idPointer _) = Just (ProxyEntry idPointer Nothing) modifier NodeEntry {} = Nothing - diff --git a/Hash2Pub/src/Hash2Pub/FediChord.hs b/Hash2Pub/src/Hash2Pub/FediChord.hs index ea2be14..17013a6 100644 --- a/Hash2Pub/src/Hash2Pub/FediChord.hs +++ b/Hash2Pub/src/Hash2Pub/FediChord.hs @@ -38,6 +38,8 @@ module Hash2Pub.FediChord ( , bsAsIpAddr , FediChordConf(..) , fediChordInit + , mkServerSocket + , resolve ) where import qualified Data.Map.Strict as Map @@ -53,6 +55,7 @@ import qualified Data.ByteString as BS import qualified Data.ByteString.UTF8 as BSU import qualified Data.ByteArray as BA import qualified Network.ByteOrder as NetworkBytes +import Data.IP (IPv6, fromHostAddress6, toHostAddress6) import Hash2Pub.Utils @@ -392,7 +395,6 @@ checkCacheSlices state = case getNodeCache state of -- Todo: DHT backend can learn potential initial bootstrapping points through the instances mentioned in the received AP-relay messages --- needs to know its own domain anyways for ID generation -- persist them on disk so they can be used for all following bootstraps -- | configuration values used for initialising the FediChord DHT @@ -402,27 +404,61 @@ data FediChordConf = FediChordConf { , confDhtPort :: Int } deriving (Show, Eq) --- | initialise data structures, compute own IDs. +-- | initialise data structures, compute own IDs and bind to listening socket -- ToDo: load persisted state, thus this function already operates in IO -fediChordInit :: FediChordConf -> IO NodeState -fediChordInit conf = return $ NodeState { - domain = confDomain conf - , ipAddr = confIP conf - , nid = genNodeID (confIP conf) (confDomain conf) 0 - , dhtPort = toEnum $ confDhtPort conf - , apPort = Nothing - , vServerID = 0 - , internals = Just internalsInit - } - where - internalsInit = InternalNodeState { - nodeCache = initCache - , successors = [] - , predecessors = [] - , kNeighbours = 3 - , lNumBestNodes = 3 - , pNumParallelQueries = 2 - , jEntriesPerSlice = 2 - } +fediChordInit :: FediChordConf -> IO (Socket, NodeState) +fediChordInit conf = do + let + initialState = NodeState { + domain = confDomain conf + , ipAddr = confIP conf + , nid = genNodeID (confIP conf) (confDomain conf) 0 + , dhtPort = toEnum $ confDhtPort conf + , apPort = Nothing + , vServerID = 0 + , internals = Just internalsInit + } + internalsInit = InternalNodeState { + nodeCache = initCache + , successors = [] + , predecessors = [] + , kNeighbours = 3 + , lNumBestNodes = 3 + , pNumParallelQueries = 2 + , jEntriesPerSlice = 2 + } + serverSock <- mkServerSocket (ipAddr initialState) (dhtPort initialState) + return (serverSock, initialState) + +--fediChordJoin :: NodeState -- ^ the local 'NodeState' +-- -> (String, PortNumber) -- ^ domain and port of a bootstrapping node +-- -> IO Either String NodeState -- ^ the joined 'NodeState' after a successful +-- -- join, otherwise an error message +--fediChordJoin + + +-- ====== network socket operations ====== + +-- | resolve a specified host and return the 'AddrInfo' for it. +-- If no hostname or IP is specified, the 'AddrInfo' can be used to bind to all +-- addresses; +-- if no port is specified an arbitrary free port is selected. +resolve :: Maybe String -- ^ hostname or IP address to be resolved + -> Maybe PortNumber -- ^ port number of either local bind or remote + -> IO AddrInfo +resolve host port = let + hints = defaultHints { addrFamily = AF_INET6, addrSocketType = Datagram + , addrFlags = [AI_PASSIVE] } + in + head <$> getAddrInfo (Just hints) host (show <$> port) + +-- | create an unconnected UDP Datagram 'Socket' bound to the specified address +mkServerSocket :: HostAddress6 -> PortNumber -> IO Socket +mkServerSocket ip port = do + sockAddr <- addrAddress <$> resolve (Just $ show . fromHostAddress6 $ ip) (Just port) + sock <- socket AF_INET6 Datagram defaultProtocol + setSocketOption sock IPv6Only 1 + bind sock sockAddr + return sock diff --git a/Hash2Pub/src/Hash2Pub/Main.hs b/Hash2Pub/src/Hash2Pub/Main.hs index 3f6e9ff..67d75f2 100644 --- a/Hash2Pub/src/Hash2Pub/Main.hs +++ b/Hash2Pub/src/Hash2Pub/Main.hs @@ -11,8 +11,9 @@ main = do -- probably use `tomland` for that conf <- readConfig -- ToDo: load persisted caches, bootstrapping nodes … - thisNode <- fediChordInit conf + (serverSock, thisNode) <- fediChordInit conf print thisNode + print serverSock return () readConfig :: IO FediChordConf