mirror of https://github.com/voidlizard/hbs2
still working
This commit is contained in:
parent
39d7e0c035
commit
4008971946
|
@ -91,11 +91,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1673163619,
|
"lastModified": 1673800717,
|
||||||
"narHash": "sha256-B33PFBL64ZgTWgMnhFL3jgheAN/DjHPsZ1Ih3z0VE5I=",
|
"narHash": "sha256-SFHraUqLSu5cC6IxTprex/nTsI81ZQAtDvlBvGDWfnA=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "8c54d842d9544361aac5f5b212ba04e4089e8efe",
|
"rev": "2f9fd351ec37f5d479556cd48be4ca340da59b8f",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
@ -75,6 +75,7 @@ library
|
||||||
, HBS2.Net.Messaging.Fake
|
, HBS2.Net.Messaging.Fake
|
||||||
, HBS2.Net.PeerLocator
|
, HBS2.Net.PeerLocator
|
||||||
, HBS2.Net.PeerLocator.Static
|
, HBS2.Net.PeerLocator.Static
|
||||||
|
, HBS2.Net.Peer
|
||||||
, HBS2.Net.Proto
|
, HBS2.Net.Proto
|
||||||
, HBS2.Net.Proto.Types
|
, HBS2.Net.Proto.Types
|
||||||
, HBS2.Net.Proto.Actors.BlockInfo
|
, HBS2.Net.Proto.Actors.BlockInfo
|
||||||
|
@ -101,6 +102,7 @@ library
|
||||||
, interpolatedstring-perl6
|
, interpolatedstring-perl6
|
||||||
, memory
|
, memory
|
||||||
, microlens-platform
|
, microlens-platform
|
||||||
|
, mtl
|
||||||
, prettyprinter
|
, prettyprinter
|
||||||
, safe
|
, safe
|
||||||
, serialise
|
, serialise
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
{-# Language UndecidableInstances #-}
|
||||||
|
module HBS2.Net.Peer where
|
||||||
|
|
||||||
|
import HBS2.Prelude
|
||||||
|
import HBS2.Net.Proto
|
||||||
|
import HBS2.Net.Messaging
|
||||||
|
|
||||||
|
import Data.Foldable
|
||||||
|
import Control.Monad.Reader
|
||||||
|
import Data.Map qualified as Map
|
||||||
|
import Data.Proxy
|
||||||
|
import GHC.TypeLits
|
||||||
|
|
||||||
|
data AnyMessage e = AnyMessage Integer (Encoded e)
|
||||||
|
|
||||||
|
data EngineEnv e = forall bus . (Messaging bus e (AnyMessage e)) =>
|
||||||
|
EngineEnv
|
||||||
|
{ peer :: Maybe (Peer e)
|
||||||
|
, self :: Peer e
|
||||||
|
, bus :: bus
|
||||||
|
}
|
||||||
|
|
||||||
|
data AnyProtocol e m = forall p . ( HasProtocol e p
|
||||||
|
, Response e p m
|
||||||
|
) =>
|
||||||
|
AnyProtocol
|
||||||
|
{ myProtoId :: Integer
|
||||||
|
, protoDecode :: Encoded e -> Maybe p
|
||||||
|
, protoEncode :: p -> Encoded e
|
||||||
|
, handle :: p -> m ()
|
||||||
|
}
|
||||||
|
|
||||||
|
makeResponse :: forall e p m . ( MonadIO m
|
||||||
|
, Response e p m
|
||||||
|
, HasProtocol e p
|
||||||
|
)
|
||||||
|
=> (p -> m ()) -> AnyProtocol e m
|
||||||
|
|
||||||
|
makeResponse h = AnyProtocol { myProtoId = natVal (Proxy @(ProtocolId p))
|
||||||
|
, protoDecode = decode
|
||||||
|
, protoEncode = encode
|
||||||
|
, handle = h
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
newtype EngineM e m a = EngineM { fromEngine :: ReaderT (EngineEnv e) m a }
|
||||||
|
deriving ( Functor
|
||||||
|
, Applicative
|
||||||
|
, Monad
|
||||||
|
, MonadIO
|
||||||
|
, MonadReader (EngineEnv e)
|
||||||
|
)
|
||||||
|
|
||||||
|
runEngineM :: EngineEnv e -> EngineM e m a -> m a
|
||||||
|
runEngineM e f = runReaderT (fromEngine f) e
|
||||||
|
|
||||||
|
|
||||||
|
instance (MonadIO m, HasProtocol e p) => Request e p (EngineM e m) where
|
||||||
|
request p msg = do
|
||||||
|
let proto = protoId @e @p (Proxy @p)
|
||||||
|
ask >>= \case
|
||||||
|
EngineEnv { self = s, bus = b} -> do
|
||||||
|
liftIO $ sendTo b (To p) (From s) (AnyMessage proto (encode msg))
|
||||||
|
|
||||||
|
instance (MonadIO m, HasProtocol e p) => Response e p (EngineM e m) where
|
||||||
|
response resp = do
|
||||||
|
env <- ask
|
||||||
|
let proto = protoId @e @p (Proxy @p)
|
||||||
|
case env of
|
||||||
|
(EngineEnv { peer = Just p
|
||||||
|
, bus = b
|
||||||
|
, self = s
|
||||||
|
} ) -> do
|
||||||
|
liftIO $ sendTo b (To p) (From s) (AnyMessage proto (encode resp))
|
||||||
|
_ -> pure ()
|
||||||
|
|
||||||
|
|
||||||
|
newEnv :: forall e bus m . (Monad m, Messaging bus e (AnyMessage e)) => Peer e -> bus -> m (EngineEnv e)
|
||||||
|
newEnv p pipe = pure $ EngineEnv Nothing p pipe
|
||||||
|
|
||||||
|
|
||||||
|
runPeer :: MonadIO m => EngineEnv e -> [AnyProtocol e (EngineM e m)] -> m a
|
||||||
|
runPeer env@(EngineEnv {self = me, bus = pipe}) hh = do
|
||||||
|
|
||||||
|
let resp = [ (pid, a) | a@AnyProtocol { myProtoId = pid } <- hh ]
|
||||||
|
|
||||||
|
let disp = Map.fromList resp
|
||||||
|
|
||||||
|
runEngineM env $ do
|
||||||
|
|
||||||
|
forever $ do
|
||||||
|
messages <- receive pipe (To me)
|
||||||
|
|
||||||
|
for_ messages $ \(From pip, AnyMessage n msg) -> do
|
||||||
|
|
||||||
|
local (\e -> e { peer = Just pip } ) $ do
|
||||||
|
|
||||||
|
case Map.lookup n disp of
|
||||||
|
Just (AnyProtocol {protoDecode = decoder, handle = h}) -> maybe (pure ()) h (decoder msg)
|
||||||
|
Nothing -> pure ()
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
module HBS2.Net.PeerLocator where
|
module HBS2.Net.PeerLocator where
|
||||||
|
|
||||||
-- import HBS2.Prelude
|
-- import HBS2.Prelude
|
||||||
import HBS2.Net.Proto
|
import HBS2.Net.Proto.Types
|
||||||
|
|
||||||
class PeerLocator l where
|
class PeerLocator l where
|
||||||
knownPeers :: (HasPeer p, Monad m) => l -> m [Peer p]
|
knownPeers :: (HasPeer p, Monad m) => l -> m [Peer p]
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
{-# Language TypeFamilyDependencies #-}
|
{-# Language TypeFamilyDependencies #-}
|
||||||
{-# Language FunctionalDependencies #-}
|
{-# Language FunctionalDependencies #-}
|
||||||
module HBS2.Net.Proto.Types where
|
module HBS2.Net.Proto.Types
|
||||||
|
( module HBS2.Net.Proto.Types
|
||||||
|
) where
|
||||||
|
|
||||||
import Data.Kind
|
import Data.Kind
|
||||||
import GHC.TypeLits
|
import GHC.TypeLits
|
||||||
|
|
|
@ -2,12 +2,13 @@ module HBS2.Prelude
|
||||||
( module Data.String
|
( module Data.String
|
||||||
, module Safe
|
, module Safe
|
||||||
, MonadIO(..)
|
, MonadIO(..)
|
||||||
-- , module HBS2.Prelude
|
, void
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Data.String (IsString(..))
|
import Data.String (IsString(..))
|
||||||
import Safe
|
import Safe
|
||||||
import Control.Monad.IO.Class (MonadIO(..))
|
import Control.Monad.IO.Class (MonadIO(..))
|
||||||
|
import Control.Monad (void)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,13 @@ module HasProtocol
|
||||||
( module HBS2.Net.Proto.Types
|
( module HBS2.Net.Proto.Types
|
||||||
, module HBS2.Net.Messaging
|
, module HBS2.Net.Messaging
|
||||||
, module HBS2.Net.Messaging.Fake
|
, module HBS2.Net.Messaging.Fake
|
||||||
|
, module HBS2.Net.Peer
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import HBS2.Net.Proto.Types
|
|
||||||
import HBS2.Net.Messaging
|
import HBS2.Net.Messaging
|
||||||
import HBS2.Net.Messaging.Fake
|
import HBS2.Net.Messaging.Fake
|
||||||
|
import HBS2.Net.Peer
|
||||||
|
import HBS2.Net.Proto.Types
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,113 +2,16 @@
|
||||||
{-# Language UndecidableInstances #-}
|
{-# Language UndecidableInstances #-}
|
||||||
module TestUniqProtoId where
|
module TestUniqProtoId where
|
||||||
|
|
||||||
|
import HBS2.Prelude
|
||||||
|
|
||||||
import HasProtocol
|
import HasProtocol
|
||||||
import FakeMessaging
|
import FakeMessaging
|
||||||
|
|
||||||
import GHC.TypeLits
|
|
||||||
import Data.Proxy
|
|
||||||
import Data.Map qualified as Map
|
|
||||||
import Control.Monad.Reader
|
|
||||||
|
|
||||||
import Control.Concurrent.Async
|
import Control.Concurrent.Async
|
||||||
import Data.Foldable
|
|
||||||
import Safe
|
|
||||||
|
|
||||||
import Prettyprinter hiding (pipe)
|
import Prettyprinter hiding (pipe)
|
||||||
|
|
||||||
|
|
||||||
data AnyMessage e = AnyMessage Integer (Encoded e)
|
|
||||||
|
|
||||||
data EngineEnv e = forall bus . (Messaging bus e (AnyMessage e)) =>
|
|
||||||
EngineEnv
|
|
||||||
{ peer :: Maybe (Peer e)
|
|
||||||
, self :: Peer e
|
|
||||||
, bus :: bus
|
|
||||||
}
|
|
||||||
|
|
||||||
data AnyProtocol e m = forall p . ( HasProtocol e p
|
|
||||||
, KnownNat (ProtocolId p)
|
|
||||||
, Response e p m
|
|
||||||
) =>
|
|
||||||
AnyProtocol
|
|
||||||
{ myProtoId :: Integer
|
|
||||||
, protoDecode :: Encoded e -> Maybe p
|
|
||||||
, protoEncode :: p -> Encoded e
|
|
||||||
, handle :: p -> m ()
|
|
||||||
}
|
|
||||||
|
|
||||||
makeResponse :: forall e p m . ( MonadIO m
|
|
||||||
, Response e p m
|
|
||||||
, HasProtocol e p
|
|
||||||
)
|
|
||||||
=> (p -> m ()) -> AnyProtocol e m
|
|
||||||
|
|
||||||
makeResponse h = AnyProtocol { myProtoId = natVal (Proxy @(ProtocolId p))
|
|
||||||
, protoDecode = decode
|
|
||||||
, protoEncode = encode
|
|
||||||
, handle = h
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
newtype EngineM e m a = EngineM { fromEngine :: ReaderT (EngineEnv e) m a }
|
|
||||||
deriving ( Functor
|
|
||||||
, Applicative
|
|
||||||
, Monad
|
|
||||||
, MonadTrans
|
|
||||||
, MonadIO
|
|
||||||
, MonadReader (EngineEnv e)
|
|
||||||
)
|
|
||||||
|
|
||||||
runEngineM :: EngineEnv e -> EngineM e m a -> m a
|
|
||||||
runEngineM e f = runReaderT (fromEngine f) e
|
|
||||||
|
|
||||||
|
|
||||||
instance (MonadIO m, HasProtocol e p) => Request e p (EngineM e m) where
|
|
||||||
request p msg = do
|
|
||||||
let proto = protoId @e @p (Proxy @p)
|
|
||||||
ask >>= \case
|
|
||||||
EngineEnv { self = s, bus = b} -> do
|
|
||||||
liftIO $ sendTo b (To p) (From s) (AnyMessage proto (encode msg))
|
|
||||||
|
|
||||||
instance (MonadIO m, HasProtocol e p) => Response e p (EngineM e m) where
|
|
||||||
response resp = do
|
|
||||||
env <- ask
|
|
||||||
let proto = protoId @e @p (Proxy @p)
|
|
||||||
case env of
|
|
||||||
(EngineEnv { peer = Just p
|
|
||||||
, bus = b
|
|
||||||
, self = s
|
|
||||||
} ) -> do
|
|
||||||
liftIO $ sendTo b (To p) (From s) (AnyMessage proto (encode resp))
|
|
||||||
_ -> pure ()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
newEnv :: forall e bus m . (Monad m, Messaging bus e (AnyMessage e)) => Peer e -> bus -> m (EngineEnv e)
|
|
||||||
newEnv p pipe = pure $ EngineEnv Nothing p pipe
|
|
||||||
|
|
||||||
|
|
||||||
runPeer :: MonadIO m => EngineEnv e -> [AnyProtocol e (EngineM e m)] -> m a
|
|
||||||
runPeer env@(EngineEnv {self = me, bus = pipe}) hh = do
|
|
||||||
|
|
||||||
let resp = [ (pid, a) | a@AnyProtocol { myProtoId = pid } <- hh ]
|
|
||||||
|
|
||||||
let disp = Map.fromList resp
|
|
||||||
|
|
||||||
runEngineM env $ do
|
|
||||||
|
|
||||||
forever $ do
|
|
||||||
messages <- receive pipe (To me)
|
|
||||||
|
|
||||||
for_ messages $ \(From pip, AnyMessage n msg) -> do
|
|
||||||
|
|
||||||
local (\e -> e { peer = Just pip } ) $ do
|
|
||||||
|
|
||||||
case Map.lookup n disp of
|
|
||||||
Just (AnyProtocol {protoDecode = decoder, handle = h}) -> maybe (pure ()) h (decoder msg)
|
|
||||||
Nothing -> pure ()
|
|
||||||
|
|
||||||
data PingPong e = Ping Int
|
data PingPong e = Ping Int
|
||||||
| Pong Int
|
| Pong Int
|
||||||
deriving stock (Show,Read)
|
deriving stock (Show,Read)
|
||||||
|
@ -132,13 +35,25 @@ instance HasProtocol Fake (PeekPoke Fake) where
|
||||||
encode = show
|
encode = show
|
||||||
|
|
||||||
|
|
||||||
pingPongHandler :: forall e m . (MonadIO m, Response e (PingPong e) m, HasProtocol e (PingPong e)) => PingPong e -> m ()
|
pingPongHandler :: forall e m . ( MonadIO m
|
||||||
|
, Response e (PingPong e) m
|
||||||
|
, HasProtocol e (PingPong e)
|
||||||
|
)
|
||||||
|
=> PingPong e
|
||||||
|
-> m ()
|
||||||
|
|
||||||
pingPongHandler =
|
pingPongHandler =
|
||||||
\case
|
\case
|
||||||
Ping c -> liftIO (print $ "effect: PING" <+> pretty c) >> response (Pong @e c)
|
Ping c -> liftIO (print $ "effect: PING" <+> pretty c) >> response (Pong @e c)
|
||||||
Pong c -> liftIO (print $ "effect: PONG" <+> pretty c) >> response (Ping @e (succ c))
|
Pong c -> liftIO (print $ "effect: PONG" <+> pretty c) >> response (Ping @e (succ c))
|
||||||
|
|
||||||
peekPokeHandler :: forall e m . (MonadIO m, Response e (PeekPoke e) m, HasProtocol e (PeekPoke e)) => PeekPoke e -> m ()
|
peekPokeHandler :: forall e m . ( MonadIO m
|
||||||
|
, Response e (PeekPoke e) m
|
||||||
|
, HasProtocol e (PeekPoke e)
|
||||||
|
)
|
||||||
|
=> PeekPoke e
|
||||||
|
-> m ()
|
||||||
|
|
||||||
peekPokeHandler =
|
peekPokeHandler =
|
||||||
\case
|
\case
|
||||||
Peek c -> liftIO (print $ "effect: Peek" <+> pretty c) >> response (Poke @e c)
|
Peek c -> liftIO (print $ "effect: Peek" <+> pretty c) >> response (Poke @e c)
|
||||||
|
@ -146,9 +61,8 @@ peekPokeHandler =
|
||||||
Nop -> liftIO (print $ pretty "effect: Nop") >> response (Peek @e 1)
|
Nop -> liftIO (print $ pretty "effect: Nop") >> response (Peek @e 1)
|
||||||
|
|
||||||
|
|
||||||
testUniqiProtoId :: IO ()
|
testUniqProtoId :: IO ()
|
||||||
testUniqiProtoId = do
|
testUniqProtoId = do
|
||||||
|
|
||||||
|
|
||||||
fake <- newFakeP2P True
|
fake <- newFakeP2P True
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue