content: {-# LANGUAGE RecordWildCards #-}
  
  module Hans.Types (
      module Hans.Types,
      module Exports
    ) where
  
  import Hans.Config (Config,HasConfig(..))
  import Hans.Device.Types (Device)
  import Hans.IP4.ArpTable as Exports (ArpTable)
  import Hans.IP4.Packet
  import Hans.IP4.State as Exports
  import Hans.IP4.RoutingTable as Exports (RoutingTable)
  import Hans.Lens
  import Hans.Nat.State as Exports
  import Hans.Tcp.State as Exports
  import Hans.Udp.State as Exports
  
  import           Control.Concurrent (ThreadId)
  import           Control.Concurrent.BoundedChan (BoundedChan)
  import qualified Data.ByteString as S
  import           Data.IORef (IORef,atomicModifyIORef',readIORef)
  
  
  data InputPacket = FromDevice !Device !S.ByteString
                   | FromIP4 !Device !IP4Header !S.ByteString
  
  
  data NetworkStack = NetworkStack { nsConfig :: !Config
                                     -- ^ The configuration for this instance of
                                     -- the network stack.
  
                                   , nsNat :: !NatState
                                     -- ^ Nat table/config
  
                                   , nsInput :: !(BoundedChan InputPacket)
                                     -- ^ The input packet queue
  
                                   , nsDevices :: {-# UNPACK #-} !(IORef [Device])
                                     -- ^ All registered devices
  
                                   , nsIP4State :: !IP4State
                                     -- ^ State for IP4 processing
  
                                   , nsIP4Responder :: !ThreadId
                                     -- ^ Internal IP4 responder for messages
                                     -- produced in teh fast path.
  
                                   , nsUdpState :: !UdpState
                                     -- ^ State for UDP processing
  
                                   , nsUdpResponder :: !ThreadId
                                     -- ^ Responder thread for UDP messages
                                     -- produced in the fast path.
  
                                   , nsTcpState :: !TcpState
                                     -- ^ State for TCP processing
  
                                   , nsTcpResponder :: !ThreadId
                                     -- ^ Responder thread for TCP messages
                                     -- produced in the fast path.
  
                                   , nsTcpTimers :: !ThreadId
                                     -- ^ The TCP timer thread
  
                                   , nsNameServers4 :: !(IORef [IP4])
                                   }
  
  instance HasConfig NetworkStack where
    config = to nsConfig
    {-# INLINE config #-}
  
  instance HasIP4State NetworkStack where
    ip4State = to nsIP4State
    {-# INLINE ip4State #-}
  
  instance HasUdpState NetworkStack where
    udpState = to nsUdpState
    {-# INLINE udpState #-}
  
  instance HasTcpState NetworkStack where
    tcpState = to nsTcpState
    {-# INLINE tcpState #-}
  
  instance HasNatState NetworkStack where
    natState = to nsNat
    {-# INLINE natState #-}
  
  
  
  class HasNetworkStack ns where
    networkStack :: Getting r ns NetworkStack
  
  instance HasNetworkStack NetworkStack where
    networkStack = id
    {-# INLINE networkStack #-}
  
  
  addNameServer4 :: HasNetworkStack ns => ns -> IP4 -> IO ()
  addNameServer4 ns addr =
    atomicModifyIORef' (nsNameServers4 (view networkStack ns))
        (\addrs -> (addr:addrs,()))
  
  getNameServers4 :: HasNetworkStack ns => ns -> IO [IP4]
  getNameServers4 ns = readIORef (nsNameServers4 (view networkStack ns))
  