summaryrefslogtreecommitdiff
path: root/examples/toxrelay.hs
blob: 60c2a44b4e30bf95b1bd872cd671f7aebb33e531 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
{-# LANGUAGE ScopedTypeVariables #-}

import Control.Exception
import Control.Monad
import Control.Concurrent.STM
import qualified Data.ByteString as B
import Data.Function
import qualified Data.IntMap as IntMap
         ;import Data.IntMap (IntMap)
import Data.Serialize
import System.IO
import Data.Functor.Identity

import Crypto.Tox
import Data.Tox.Relay
import Network.StreamServer
import Network.Address (getBindAddress)



hGetPrefixed :: Serialize a => Handle -> IO (Either String a)
hGetPrefixed h = do
    mlen <- runGet getWord16be <$> B.hGet h 2
    fmap join $ forM mlen $ \len -> runGet get <$> B.hGet h (fromIntegral len)

hGetSized :: forall x. (Sized x, Serialize x) => Handle -> IO (Either String x)
hGetSized h = runGet get <$> B.hGet h len
 where
    ConstSize len = size :: Size x

relaySession :: TVar (IntMap Handle) -> (RelayPacket -> IO ()) -> sock -> Int -> Handle -> IO ()
relaySession cons dispatch _ conid h = do
    atomically $ modifyTVar' cons $ IntMap.insert conid h
    mhello <- fmap (>>= decryptPayload _todo) $ hGetSized h
    B.hPut h $ encode $ encryptPayload _todo $ Welcome _todo _todo
    forM_ mhello $ \hello -> do
        let _ = hello :: Hello Identity
        fix $ \loop -> do
            m <- (>>= decrypt _todo >=> decodePlain) <$> hGetPrefixed h
            forM_ m $ \p -> do
                dispatch p
                loop
     `finally`
        atomically (modifyTVar' cons $ IntMap.delete conid)



main :: IO ()
main = do
    cons <- newTVarIO IntMap.empty
    a <- getBindAddress "33445" True
    h <- streamServer ServerConfig
                        { serverWarn = hPutStrLn stderr
                        , serverSession = relaySession cons print
                        }
                      a

    putStrLn $ "ENTER to quit..."
    s <- getLine

    quitListening h