mirror of https://github.com/voidlizard/hbs2
239 lines
6.3 KiB
Haskell
239 lines
6.3 KiB
Haskell
{-# Language TemplateHaskell #-}
|
|
module Main where
|
|
|
|
import HBS2.Prelude.Plated
|
|
import HBS2.Clock
|
|
import HBS2.Net.Proto
|
|
import HBS2.Net.Messaging.UDP
|
|
import HBS2.Net.Messaging.TCP
|
|
import HBS2.Actors.Peer
|
|
import HBS2.OrDie
|
|
|
|
import HBS2.System.Logger.Simple
|
|
|
|
import HBS2.Net.Messaging.Encrypted.ByPass
|
|
|
|
import Control.Monad.Reader
|
|
import Data.ByteString.Lazy (ByteString)
|
|
import Prettyprinter
|
|
import System.IO
|
|
import Lens.Micro.Platform
|
|
import Crypto.Saltine.Core.Sign
|
|
|
|
import Data.Int
|
|
import Codec.Serialise
|
|
-- import Control.Concurrent.Async
|
|
import System.Random
|
|
import Text.InterpolatedString.Perl6 (qc)
|
|
|
|
import Control.Monad.Trans.Resource
|
|
import UnliftIO.Async
|
|
|
|
type UDP = L4Proto
|
|
|
|
data PingPong e = Ping Int
|
|
| Pong Int
|
|
| Poke
|
|
deriving stock (Eq,Generic,Show,Read)
|
|
|
|
|
|
instance Serialise (PingPong e)
|
|
|
|
instance HasProtocol UDP (PingPong UDP) where
|
|
type instance ProtocolId (PingPong UDP) = 1307114574
|
|
type instance Encoded UDP = ByteString
|
|
decode = either (const Nothing) Just . deserialiseOrFail
|
|
encode = serialise
|
|
|
|
pingPongHandler :: forall e m . ( MonadIO m
|
|
, Response e (PingPong e) m
|
|
, HasProtocol e (PingPong e)
|
|
, HasOwnPeer e m
|
|
, Pretty (Peer e)
|
|
)
|
|
=> Int
|
|
-> PingPong e
|
|
-> m ()
|
|
|
|
pingPongHandler n = \case
|
|
|
|
Poke -> pure ()
|
|
|
|
Ping c -> do
|
|
self <- ownPeer @e
|
|
debug ("Ping" <+> pretty self <+> pretty c) >> response (Pong @e c)
|
|
|
|
Pong c | c < n -> do
|
|
self <- ownPeer @e
|
|
debug ("Pong" <+> pretty self <+> pretty c) >> response (Ping @e (succ c))
|
|
|
|
| otherwise -> pure ()
|
|
|
|
data PPEnv =
|
|
PPEnv
|
|
{ _ppSelf :: Peer UDP
|
|
, _ppFab :: Fabriq UDP
|
|
}
|
|
|
|
makeLenses 'PPEnv
|
|
|
|
newtype PingPongM m a = PingPongM { fromPingPong :: ReaderT PPEnv m a }
|
|
deriving newtype ( Functor
|
|
, Applicative
|
|
, Monad
|
|
, MonadIO
|
|
, MonadUnliftIO
|
|
, MonadReader PPEnv
|
|
, MonadTrans
|
|
)
|
|
|
|
runPingPong :: (MonadIO m) => Peer UDP -> Fabriq UDP -> PingPongM m a -> m a
|
|
runPingPong pip udp m = runReaderT (fromPingPong m) (PPEnv pip udp)
|
|
|
|
instance Monad m => HasFabriq UDP (PingPongM m) where
|
|
getFabriq = asks (view ppFab)
|
|
|
|
instance Monad m => HasOwnPeer UDP (PingPongM m) where
|
|
ownPeer = asks (view ppSelf)
|
|
|
|
instance HasTimeLimits UDP (PingPong UDP) IO where
|
|
tryLockForPeriod _ _ = pure True
|
|
|
|
tracePrefix :: SetLoggerEntry
|
|
tracePrefix = logPrefix "[trace] "
|
|
|
|
debugPrefix :: SetLoggerEntry
|
|
debugPrefix = logPrefix "[debug] "
|
|
|
|
errorPrefix :: SetLoggerEntry
|
|
errorPrefix = logPrefix "[error] "
|
|
|
|
warnPrefix :: SetLoggerEntry
|
|
warnPrefix = logPrefix "[warn] "
|
|
|
|
noticePrefix :: SetLoggerEntry
|
|
noticePrefix = logPrefix "[RT] "
|
|
|
|
|
|
testUDP :: IO ()
|
|
testUDP = runResourceT do
|
|
|
|
let o = byPassDef
|
|
|
|
udp1 <- newMessagingUDP False (Just "127.0.0.1:10001") `orDie` "Can't start listener on 10001"
|
|
udp2 <- newMessagingUDP False (Just "127.0.0.1:10002") `orDie` "Can't start listener on 10002"
|
|
|
|
Keypair s1 p1 <- liftIO newKeypair
|
|
pass1 <- newByPassMessaging @UDP o udp1 (getOwnPeer udp1) p1 s1
|
|
|
|
Keypair s2 p2 <- liftIO newKeypair
|
|
pass2 <- newByPassMessaging @UDP o udp2 (getOwnPeer udp2) p2 s2
|
|
|
|
m1 <- async $ runMessagingUDP udp1
|
|
m2 <- async $ runMessagingUDP udp2
|
|
|
|
let own1 = getOwnPeer udp1
|
|
let own2 = getOwnPeer udp2
|
|
|
|
peer1 <- async $ runPingPong own1 (Fabriq pass1) do
|
|
proto <- async $ runProto @UDP
|
|
[ makeResponse (pingPongHandler 10)
|
|
]
|
|
link proto
|
|
forever (pause @'Seconds 10)
|
|
|
|
|
|
peer2 <- async $ runPingPong own2 (Fabriq pass2) do
|
|
proto <- async $ runProto @UDP
|
|
[ makeResponse (pingPongHandler 10)
|
|
]
|
|
link proto
|
|
request (getOwnPeer udp1) (Ping @UDP 0)
|
|
forever (pause @'Seconds 10)
|
|
|
|
mapM_ wait [peer1,peer2,m1,m2]
|
|
|
|
|
|
testTCP :: IO ()
|
|
testTCP = runResourceT do
|
|
|
|
let o = byPassDef
|
|
|
|
pn1 <- liftIO $ randomIO @Int8 <&> ((11000 +) . fromIntegral)
|
|
pn2 <- liftIO $ randomIO @Int8 <&> ((11000 +). fromIntegral)
|
|
|
|
let addr1 = fromString [qc|tcp://127.0.0.1:{pn1}|]
|
|
let addr2 = fromString [qc|tcp://127.0.0.1:{pn2}|]
|
|
|
|
debug $ "ADDR1" <+> pretty addr1
|
|
debug $ "ADDR2" <+> pretty addr2
|
|
|
|
me1 <- newMessagingTCP addr1
|
|
me2 <- newMessagingTCP addr2
|
|
|
|
m1 <- async $ runMessagingTCP me1
|
|
m2 <- async $ runMessagingTCP me2
|
|
|
|
let peer1 = view tcpOwnPeer me1
|
|
let peer2 = view tcpOwnPeer me2
|
|
|
|
|
|
Keypair s1 p1 <- liftIO newKeypair
|
|
pass1 <- newByPassMessaging o me1 peer1 p1 s1
|
|
|
|
Keypair s2 p2 <- liftIO newKeypair
|
|
pass2 <- newByPassMessaging o me2 peer2 p2 s2
|
|
|
|
peerThread1 <- async $ runPingPong peer1 (Fabriq pass1) do
|
|
proto <- async $ runProto @L4Proto
|
|
[ makeResponse (pingPongHandler 10)
|
|
]
|
|
link proto
|
|
|
|
request peer2 (Poke @L4Proto)
|
|
|
|
pause @'Seconds 1
|
|
|
|
request peer2 (Ping @L4Proto 0)
|
|
|
|
forever (pause @Seconds 10)
|
|
|
|
|
|
peerThread2 <- async $ runPingPong peer2 (Fabriq pass2) do
|
|
proto <- async $ runProto @L4Proto
|
|
[ makeResponse (pingPongHandler 10)
|
|
]
|
|
link proto
|
|
forever (pause @Seconds 10)
|
|
|
|
waiter <- async $ do
|
|
pause @'Seconds 3
|
|
|
|
void $ waitAnyCatchCancel [peerThread1,peerThread2,m1,m2,waiter]
|
|
|
|
stat1 <- getStat pass1
|
|
stat2 <- getStat pass2
|
|
|
|
debug "testUDP done"
|
|
|
|
liftIO $ print $ "peer1 stats" <> line <> indent 4 (pretty stat1) <> line
|
|
liftIO $ print $ "peer2 stats" <> line <> indent 4 (pretty stat2) <> line
|
|
|
|
|
|
main :: IO ()
|
|
main = do
|
|
|
|
liftIO $ hSetBuffering stdout LineBuffering
|
|
liftIO $ hSetBuffering stderr LineBuffering
|
|
|
|
setLogging @DEBUG debugPrefix
|
|
setLogging @INFO defLog
|
|
setLogging @ERROR errorPrefix
|
|
setLogging @WARN warnPrefix
|
|
setLogging @NOTICE noticePrefix
|
|
setLogging @TRACE tracePrefix
|
|
|
|
testTCP
|
|
|
|
|