summaryrefslogtreecommitdiff
path: root/src/Network/SessionTransports.hs
diff options
context:
space:
mode:
authorJames Crayne <jim.crayne@gmail.com>2019-09-28 13:43:29 -0400
committerJoe Crayne <joe@jerkface.net>2020-01-01 19:27:53 -0500
commit11987749fc6e6d3e53ea737d46d5ab13a16faeb8 (patch)
tree5716463275c2d3e902889db619908ded2a73971c /src/Network/SessionTransports.hs
parentadd2c76bced51fde5e9917e7449ef52be70faf87 (diff)
Factor out some new libraries
word64-map: Data.Word64Map network-addr: Network.Address tox-crypto: Crypto.Tox lifted-concurrent: Control.Concurrent.Lifted.Instrument Control.Concurrent.Async.Lifted.Instrument psq-wrap: Data.Wrapper.PSQInt Data.Wrapper.PSQ minmax-psq: Data.MinMaxPSQ tasks: Control.Concurrent.Tasks kad: Network.Kademlia Network.Kademlia.Bootstrap Network.Kademlia.Routing Network.Kademlia.CommonAPI Network.Kademlia.Persistence Network.Kademlia.Search
Diffstat (limited to 'src/Network/SessionTransports.hs')
-rw-r--r--src/Network/SessionTransports.hs98
1 files changed, 0 insertions, 98 deletions
diff --git a/src/Network/SessionTransports.hs b/src/Network/SessionTransports.hs
deleted file mode 100644
index e9daf6c1..00000000
--- a/src/Network/SessionTransports.hs
+++ /dev/null
@@ -1,98 +0,0 @@
1{-# LANGUAGE NamedFieldPuns #-}
2module Network.SessionTransports
3 ( Sessions
4 , initSessions
5 , newSession
6 , sessionHandler
7 ) where
8
9import Control.Concurrent
10import Control.Concurrent.STM
11import Control.Monad
12import qualified Data.IntMap.Strict as IntMap
13 ;import Data.IntMap.Strict (IntMap)
14import qualified Data.Map.Strict as Map
15 ;import Data.Map.Strict (Map)
16
17import Network.Address (SockAddr,either4or6)
18import Network.QueryResponse
19import qualified Data.IntervalSet as S
20 ;import Data.IntervalSet (IntSet)
21
22data Sessions x = Sessions
23 { sessionsByAddr :: TVar (Map SockAddr (IntMap (x -> IO Bool)))
24 , sessionsById :: TVar (IntMap SockAddr)
25 , sessionIds :: TVar IntSet
26 , sessionsSendRaw :: SockAddr -> x -> IO ()
27 }
28
29initSessions :: (SockAddr -> x -> IO ()) -> IO (Sessions x)
30initSessions send = atomically $ do
31 byaddr <- newTVar Map.empty
32 byid <- newTVar IntMap.empty
33 idset <- newTVar S.empty
34 return Sessions { sessionsByAddr = byaddr
35 , sessionsById = byid
36 , sessionIds = idset
37 , sessionsSendRaw = send
38 }
39
40
41
42rmSession :: Int -> (Maybe (IntMap x)) -> (Maybe (IntMap x))
43rmSession sid Nothing = Nothing
44rmSession sid (Just m) = case IntMap.delete sid m of
45 m' | IntMap.null m' -> Nothing
46 | otherwise -> Just m'
47
48newSession :: Sessions raw
49 -> (addr -> y -> IO raw)
50 -> (SockAddr -> raw -> IO (Maybe (x, addr)))
51 -> SockAddr
52 -> IO (Maybe (Int,TransportA err addr x y))
53newSession Sessions{sessionsByAddr,sessionsById,sessionIds,sessionsSendRaw} unwrap wrap addr0 = do
54 mvar <- newEmptyMVar
55 let saddr = -- Canonical in case of 6-mapped-4 addresses.
56 either id id $ either4or6 addr0
57 handlePacket x = do
58 m <- wrap saddr x
59 case m of
60 Nothing -> return False
61 Just x' -> do putMVar mvar $! Just $! x'
62 return True
63 msid <- atomically $ do
64 msid <- S.nearestOutsider 0 <$> readTVar sessionIds
65 forM msid $ \sid -> do
66 modifyTVar' sessionIds $ S.insert sid
67 modifyTVar' sessionsById $ IntMap.insert sid saddr
68 modifyTVar' sessionsByAddr $ Map.insertWith IntMap.union saddr
69 $ IntMap.singleton sid handlePacket
70 return sid
71 forM msid $ \sid -> do
72 let tr = Transport
73 { awaitMessage = \kont -> do
74 x <- takeMVar mvar
75 kont $! Right <$> x
76 , sendMessage = \addr x -> do
77 x' <- unwrap addr x
78 sessionsSendRaw saddr x'
79 , closeTransport = do
80 tryTakeMVar mvar
81 putMVar mvar Nothing
82 atomically $ do
83 modifyTVar' sessionIds $ S.delete sid
84 modifyTVar' sessionsById $ IntMap.delete sid
85 modifyTVar' sessionsByAddr $ Map.alter (rmSession sid) saddr
86 }
87 return (sid,tr)
88
89sessionHandler :: Sessions x -> (SockAddr -> x -> IO (Maybe (x -> x)))
90sessionHandler Sessions{sessionsByAddr} = \addr0 x -> do
91 let addr = -- Canonical in case of 6-mapped-4 addresses.
92 either id id $ either4or6 addr0
93 dispatch [] = return ()
94 dispatch (f:fs) = do b <- f x
95 when (not b) $ dispatch fs
96 fs <- atomically $ Map.lookup addr <$> readTVar sessionsByAddr
97 mapM_ (dispatch . IntMap.elems) fs
98 return Nothing -- consume all packets.