module Net.EthernetClient where

import Net.Concurrent(fork)
import Net.Ethernet as Eth(Interface(..),Packet,PacketType(..),rx,tx,packType,content)
import qualified Net.IPv4 as IPv4(Packet)
import qualified Net.ARP as ARP(Packet)
import Net.PacketParsing
import Net.Wire
import qualified Net.Interface as Net
import Monad.Util(loop)

type Client_ m p = Eth.Interface m p (Packet p)
type Client m p = Eth.Interface m (p InPacket) (Packet (p OutPacket))

data Clients m
    = Clients {
--        ethernet,
--        unknown   :: Client m Packet,
        ipv4      :: Client m IPv4.Packet,
--      ipv6      :: Client m IPv6.Packet,
	arp       :: Client_ m ARP.Packet
      }

initialize debug eth =
  do Net.Interface{Net.rx=rxIPv4,Net.tx=toIPv4} <- newWire()
     Net.Interface{Net.rx=rxARP,Net.tx=toARP}   <- newWire()
     let demultiplex =
	   do p <- rx eth
	      let t = packType p
		  conv dest = maybe warning dest (doParse (content p))
		  warning = debug (show t++" packet parser failed "++show p)
	      --debug (show t++" received")
	      case t of
		--Ethernet n -> to' ethernet
		IPv4       -> conv toIPv4
		--IPv6       -> return () -- not implemented yet
		ARP        -> conv toARP
		--Unknown n  -> to' unknown
		_ -> debug $ show t++" packet dropped"
         --client :: IO (...) -> Net.IOInterface ... ...
	 client rx = eth {io=io}
           where
	     io = Net.Interface {Net.rx=rx,
				 Net.tx=tx eth . fmap doUnparse}
     fork $ loop demultiplex
     return Clients {ipv4 =client rxIPv4, arp=client rxARP}
     --return (client rxIPv4,client rxARP)