hans-2.1.0.0: src/Hans/Layer/Tcp/Monad.hs
module Hans.Layer.Tcp.Monad where
import Hans.Channel
import Hans.Layer
import Hans.Layer.IP4
import Hans.Layer.Timer
import MonadLib
import Network.TCP.Type.Datagram (IPMessage)
import Network.TCP.Type.Socket (Host(..),empty_host,TCPSocket)
import Network.TCP.Type.Syscall (SocketID)
import qualified Data.Map as Map
-- TCP Monad -------------------------------------------------------------------
type TcpHandle = Channel (Tcp ())
type Tcp = Layer (TcpState (IO ()))
data TcpState t = TcpState
{ tcpSelf :: TcpHandle
, tcpIP4 :: IP4Handle
, tcpTimers :: TimerHandle
, tcpHost :: Host t
}
emptyTcpState :: TcpHandle -> IP4Handle -> TimerHandle -> TcpState t
emptyTcpState tcp ip4 timer = TcpState
{ tcpSelf = tcp
, tcpIP4 = ip4
, tcpTimers = timer
, tcpHost = empty_host
}
-- | The handle to this layer.
self :: Tcp TcpHandle
self = tcpSelf `fmap` get
-- | Get the handle to the IP4 layer.
ip4Handle :: Tcp IP4Handle
ip4Handle = tcpIP4 `fmap` get
-- | Get the handle to the Timer layer.
timerHandle :: Tcp TimerHandle
timerHandle = tcpTimers `fmap` get
-- Compatibility Layer ---------------------------------------------------------
type HMonad t = Layer (TcpState t)
get_host :: HMonad t (Host t)
get_host = tcpHost `fmap` get
put_host :: Host t -> HMonad t ()
put_host h = do
s <- get
set $! s { tcpHost = h }
modify_host :: (Host t -> Host t) -> HMonad t ()
modify_host f = do
h <- get_host
put_host $! f h
emit_segs :: [IPMessage] -> HMonad t ()
emit_segs segs = modify_host (\h -> h { output_queue = output_queue h ++ segs })
emit_ready :: [t] -> HMonad t ()
emit_ready ts = modify_host (\h -> h { ready_list = ready_list h ++ ts })
has_sock :: SocketID -> HMonad t Bool
has_sock sid = (Map.member sid . sock_map) `fmap` get_host
lookup_sock :: SocketID -> HMonad t (TCPSocket t)
lookup_sock sid = do
h <- get_host
case Map.lookup sid (sock_map h) of
Nothing -> fail "lookup_sock: sid not found"
Just res -> return res
delete_sock :: SocketID -> HMonad t ()
delete_sock sid =
modify_host (\h -> h { sock_map = Map.delete sid (sock_map h) } )
update_sock :: SocketID -> (TCPSocket t -> TCPSocket t) -> HMonad t ()
update_sock sid f =
modify_host (\h -> h { sock_map = Map.adjust f sid (sock_map h) })
insert_sock :: SocketID -> TCPSocket t -> HMonad t ()
insert_sock sid sock = do
modify_host (\h -> h { sock_map = Map.insert sid sock (sock_map h) })