packages feed

hans-2.1.0.0: src/Hans/Setup.hs

{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE DeriveDataTypeable        #-}
{-# LANGUAGE FlexibleInstances         #-}

module Hans.Setup where

import Hans.Address
import Hans.Address.IP4
import Hans.Address.Mac
import Hans.Channel
import Hans.Layer.Arp
import Hans.Layer.Ethernet
import Hans.Layer.IP4
import Hans.Layer.Icmp4
import Hans.Layer.Tcp
import Hans.Layer.Timer
import Hans.Layer.Udp


data NetworkStack = NetworkStack
  { nsArp       :: ArpHandle
  , nsEthernet  :: EthernetHandle
  , nsIp4       :: IP4Handle
  , nsIcmp4     :: Icmp4Handle
  , nsTimers    :: TimerHandle
  , nsUdp       :: UdpHandle
  , nsTcp       :: TcpHandle
  }


setup :: IO NetworkStack
setup  = do
  eth  <- newChannel
  arp  <- newChannel
  ip4  <- newChannel
  icmp <- newChannel
  th   <- newChannel
  udp  <- newChannel
  tcp  <- newChannel

  runTimerLayer    th
  runEthernetLayer eth
  runArpLayer      arp  eth th
  runIP4Layer      ip4  arp eth
  runIcmp4Layer    icmp ip4
  runUdpLayer      udp  ip4 icmp
  runTcpLayer      tcp  ip4 th

  return NetworkStack
    { nsArp     = arp
    , nsEthernet= eth
    , nsIp4     = ip4
    , nsIcmp4   = icmp
    , nsTimers  = th
    , nsUdp     = udp
    , nsTcp     = tcp
    }


data SomeOption = forall o. Option o => SomeOption o

instance Show SomeOption where
  showsPrec p (SomeOption o) = parens (showsPrec 11 o)
    where
    parens body | p > 10    = showString "(SomeOption " . body . showChar ')'
                | otherwise = showString "SomeOption " . body

toOption :: Option o => o -> SomeOption
toOption  = SomeOption

class Show o => Option o where
  apply :: o -> NetworkStack -> IO ()


instance Option SomeOption where
  apply (SomeOption o) ns = apply o ns

instance Option o => Option [o] where
  apply os ns = mapM_ (`apply` ns) os


data OptEthernet mask = LocalEthernet mask Mac
    deriving Show

instance Option (OptEthernet IP4Mask) where
  apply (LocalEthernet mask mac) ns = do
    let (addr,_) = getMaskComponents mask
    addLocalAddress (nsArp ns) addr mac
    addIP4RoutingRule (nsIp4 ns) (Direct mask addr 1500)


data OptRoute mask addr = Route mask addr
    deriving Show

instance Option (OptRoute IP4Mask IP4) where
  apply (Route mask addr) ns = addIP4RoutingRule (nsIp4 ns) (Indirect mask addr)