module Hans.Simple (
renderUdp
, renderIp4
, 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
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
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)