module Hans.Simple ( -- * UDP Messages renderUdp , renderIp4 -- * Ident , Ident , newIdent , nextIdent ) where import Hans.Address.IP4 (IP4) import Hans.Message.Ip4 (IP4Header(..),IP4Protocol(..) ,mkIP4PseudoHeader,splitPacket ,renderIP4Packet,emptyIP4Header) import Hans.Message.Udp (UdpHeader(..),UdpPort,renderUdpPacket) import qualified Hans.Message.Ip4 as IP4 import Control.Concurrent (MVar,newMVar,modifyMVar) import Data.Word (Word16) import qualified Data.ByteString.Lazy as L newtype Ident = Ident (MVar IP4.Ident) newIdent :: IO Ident newIdent = Ident `fmap` newMVar 0 nextIdent :: Ident -> IO IP4.Ident nextIdent (Ident var) = modifyMVar var (\i -> return (i+1, i)) type MTU = Word16 fromMTU :: Maybe MTU -> Int fromMTU = maybe ip4Max (min ip4Max . fromIntegral) where ip4Max = 0xffff -- | Render a UDP message to an unfragmented IP4 packet. renderUdp :: Ident -> Maybe MTU -> IP4 -> IP4 -> UdpPort -> UdpPort -> L.ByteString -> IO [L.ByteString] renderUdp i mb source dest srcPort destPort payload = do let prot = IP4Protocol 0x11 let mk = mkIP4PseudoHeader source dest prot let hdr = UdpHeader { udpSourcePort = srcPort , udpDestPort = destPort , udpChecksum = 0 } udp <- renderUdpPacket hdr payload mk renderIp4 i mb prot source dest udp -- | Render an IP4 packet. renderIp4 :: Ident -> Maybe MTU -> IP4Protocol -> IP4 -> IP4 -> L.ByteString -> IO [L.ByteString] renderIp4 ident mb prot source dest payload = do i <- nextIdent ident let hdr = emptyIP4Header { ip4Protocol = prot , ip4SourceAddr = source , ip4DestAddr = dest , ip4Ident = i } mapM (uncurry renderIP4Packet) (splitPacket (fromMTU mb) hdr payload)