module Net.TCP where
import Net.Bits
import Net.PacketParsing
import Net.PortNumber(Port(..))
import Net.Utils(Container(..))
data Packet content = Packet
{ sourcePort, destPort :: !Port,
seqNr, ackNr :: !Word32,
dataOffset :: !Word8,
ecn :: !ECN,
controlBits :: !ControlBits,
window :: !Word16,
checksum :: !Word16,
urgentPointer :: !Word16,
options :: ![Option],
content :: !content }
deriving (Show)
template = Packet (Port 0) (Port 0) 0 0 5 minBound minBound 1400 0 0 [] ()
instance Functor Packet where fmap f p = p{content=f (content p)}
instance Container Packet where contents = content
data ECN = ECN { n,c,e:: !Bool }
deriving (Show,Bounded)
data ControlBits = CB { urg,ack,psh,rst,syn,fin:: !Bool }
deriving (Eq,Bounded,Show)
type Option = Word8
instance Parse content => Parse (Packet content) where
parse = do (sp,dp,sqn,ackn) <- parse
hl <- bits 4
skip 3
let olen = (hl5)*4
Packet sp dp sqn ackn hl
# parse
<# parse
<# parse
<# parse
<# parse
<# bytes olen
<# parse
where
skip :: Int -> PacketParser Word32
skip = bits
instance Parse ControlBits where
parse = CB # parse <# parse <# parse <# parse <# parse <# parse
instance Parse ECN where
parse = ECN # parse <# parse <# parse
instance Unparse content => Unparse (Packet content) where
unparse (Packet sp dp snr anr hl ecn cb w s u o c) =
unparse (sp,dp,snr,anr) .
unparse ((ext hl << 12 .|. ecnB ecn << 6 .|. cbB cb)::Word16) .
unparse (w,s,u,o,c)
where
(<<) = shiftL
ext = fromIntegral
ecnB (ECN n c e) = toBits [n,c,e]
cbB (CB u a p r s f) = toBits [u,a,p,r,s,f]
toBits bs = fromIntegral (foldl bit 0 bs)
where bit w b = w `shiftL` 1 .|. fromEnum (b::Bool)