hans-3.0.2: src/Hans/Tcp/Message.hs
{-# LANGUAGE RecordWildCards #-}
module Hans.Tcp.Message where
import Hans.Lens
import Hans.Tcp.Packet
import Hans.Tcp.Tcb
import qualified Data.ByteString as S
import Data.IORef (readIORef)
-- | @<SEQ=SEG.ACK><CTL=RST>@
mkRst :: TcpHeader -> IO TcpHeader
mkRst TcpHeader { .. } =
return $ set tcpRst True
$ emptyTcpHeader { tcpSourcePort = tcpDestPort
, tcpDestPort = tcpSourcePort
, tcpSeqNum = tcpAckNum
}
{-# INLINE mkRst #-}
-- | @<SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>@
mkRstAck :: TcpHeader -> S.ByteString -> IO TcpHeader
mkRstAck hdr @ TcpHeader { .. } payload =
return $ set tcpRst True
$ set tcpAck True
$ emptyTcpHeader { tcpSourcePort = tcpDestPort
, tcpDestPort = tcpSourcePort
, tcpSeqNum = 0
, tcpAckNum = tcpSegNextAckNum hdr (S.length payload)
}
{-# INLINE mkRstAck #-}
mkSyn :: Tcb -> IO TcpHeader
mkSyn Tcb { .. } =
do iss <- readIORef tcbIss
return $ set tcpSyn True
$ emptyTcpHeader { tcpSourcePort = tcbRemotePort
, tcpDestPort = tcbLocalPort
, tcpSeqNum = iss
, tcpAckNum = 0
}
{-# INLINE mkSyn #-}
-- | @<SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>@
mkSynAck :: Tcb -> TcpHeader -> IO TcpHeader
mkSynAck Tcb { .. } TcpHeader { .. } =
do iss <- readIORef tcbIss
ack <- getRcvNxt tcbRecvWindow
return $ set tcpSyn True
$ set tcpAck True
$ emptyTcpHeader { tcpSourcePort = tcpDestPort
, tcpDestPort = tcpSourcePort
, tcpSeqNum = iss
, tcpAckNum = ack
}
{-# INLINE mkSynAck #-}
mkAck :: TcpSeqNum -- ^ SEG.SEQ
-> TcpSeqNum -- ^ SEG.ACK
-> TcpPort -- ^ Local port
-> TcpPort -- ^ Remote port
-> IO TcpHeader
mkAck segSeq segAck local remote =
return $ set tcpAck True
$ emptyTcpHeader { tcpSourcePort = local
, tcpDestPort = remote
, tcpSeqNum = segSeq
, tcpAckNum = segAck
}
{-# INLINE mkAck #-}