{-# 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) -- | @@ mkRst :: TcpHeader -> IO TcpHeader mkRst TcpHeader { .. } = return $ set tcpRst True $ emptyTcpHeader { tcpSourcePort = tcpDestPort , tcpDestPort = tcpSourcePort , tcpSeqNum = tcpAckNum } {-# INLINE mkRst #-} -- | @@ 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 #-} -- | @@ 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 #-}