packages feed

hans-pfq-0.1.0.0: example/gal.hs

{-# LANGUAGE CPP #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE OverloadedStrings #-}

module Main where

import Hans.Address
import Hans.DhcpClient
import Hans.Address.Mac
import Hans.Address.IP4
import Hans.NetworkStack

-- switch backends
#define PFQ

#ifdef HaLVM_HOST_OS
import Hans.Device.Xen
import Hypervisor.Console
import Hypervisor.XenStore
import XenDevice.NIC
#endif

#ifdef TAP
import Hans.Device.Tap
#endif

#ifdef PCAP
import Hans.Device.Pcap
#endif

#ifdef PFQ
import Hans.Device.PFq
#endif

import Control.Concurrent (newEmptyMVar,putMVar,takeMVar,threadDelay,forkIO
                          ,killThread,myThreadId)
import Control.Monad (forever,when)
import System.Environment (getArgs)
import qualified Data.ByteString.Lazy as L


localAddr :: IP4
localAddr  = IP4 192 168 90 2

main :: IO ()
main  = do
  ns  <- newNetworkStack
  mac <- initEthernetDevice ns
  deviceUp ns mac
  putStrLn "Network stack running..."

  args <- getArgs
  if args == ["dhcp"]
     then do putStrLn "Discovering address"
             res <- newEmptyMVar
             dhcpDiscover ns mac (putMVar res)
             ip  <- takeMVar res
             putStrLn ("Bound to address: " ++ show ip)

             putStrLn "Looking up galois.com..."
             HostEntry { .. } <- getHostByName ns "galois.com"
             print hostAddresses

             server ns ip

     else do setAddress mac ns
             server ns localAddr

server :: NetworkStack -> IP4 -> IO ()
server ns ip = do
  sock <- listen ns ip 9001

  forever $ do
    putStrLn "Waiting..."
    conn <- accept sock
    _    <- forkIO (handleClient conn)
    return ()

handleClient :: Socket -> IO ()
handleClient conn =
  do putStrLn ("Got one: " ++ show (sockRemoteHost conn))
     loop
  where
  loop =
    do buf <- recvBytes conn 512
       if L.null buf
          then do putStrLn "Client closed connection"
                  close conn
          else do _ <- sendBytes conn buf
                  loop

message :: L.ByteString
message  = "Hello, world\n"

sleep :: Int -> IO ()
sleep s = threadDelay (s * 1000 * 1000)

setAddress :: Mac -> NetworkStack -> IO ()
setAddress mac ns = do
  addIP4Addr ns (localAddr `withMask` 24) mac 1500
  routeVia ns (IP4 0 0 0 0 `withMask` 0) (IP4 192 168 90 1)

#ifdef HaLVM_HOST_OS
initEthernetDevice :: NetworkStack -> IO Mac
initEthernetDevice ns =
  do xs <- initXenStore
     _ <- initXenConsole -- should set up putStrLn
     nics <- listNICs xs
     case nics of
       [] -> fail "No NICs found to use!"
       (macstr:_) ->
         do let mac = read macstr
            nic <- openNIC xs macstr 
            addDevice ns mac (xenSend nic) (xenReceiveLoop nic)
            return mac
#endif

#ifdef TAP
dname = "tap6"
initEthernetDevice :: NetworkStack -> IO Mac
initEthernetDevice ns = do
  let mac = Mac 0x52 0x54 0x00 0x12 0x34 0x56
  Just dev <- openTapDevice dname
  addDevice ns mac (tapSend dev) (tapReceiveLoop dev)
  return mac
#endif

#ifdef PCAP
dname = "eth0"
initEthernetDevice :: NetworkStack -> IO Mac
initEthernetDevice ns = do
     let mac = Mac 0x12 0x34 0x56 0x78 0x9A 0xBC
     dev <- pcapOpen dname
     addDevice ns mac (pcapSend dev) (pcapReceiveLoop dev)
     return mac
#endif

#ifdef PFQ
dname = "eth0"
initEthernetDevice :: NetworkStack -> IO Mac
initEthernetDevice ns = do
     let mac = Mac 0x12 0x34 0x56 0x78 0x9A 0xBC
     dev <- pfqOpen dname
     addDevice ns mac (pfqSend dev) (pfqReceiveLoop dev)
     return mac
#endif