//! Transform an "absolute" 64-bit sequence number (zero-indexed) into a WrappingInt32 //! \param n The input absolute 64-bit sequence number //! \param isn The initial sequence number WrappingInt32 wrap(uint64_t n, WrappingInt32 isn){ DUMMY_CODE(n, isn); WrappingInt32 res(n+isn.raw_value()); return res; }
//! Transform a WrappingInt32 into an "absolute" 64-bit sequence number (zero-indexed) //! \param n The relative sequence number //! \param isn The initial sequence number //! \param checkpoint A recent absolute 64-bit sequence number //! \returns the 64-bit sequence number that wraps to `n` and is closest to `checkpoint` //! //! \note Each of the two streams of the TCP connection has its own ISN. One stream //! runs from the local TCPSender to the remote TCPReceiver and has one ISN, //! and the other stream runs from the remote TCPSender to the local TCPReceiver and //! has a different ISN. uint64_tunwrap(WrappingInt32 n, WrappingInt32 isn, uint64_t checkpoint){ DUMMY_CODE(n, isn, checkpoint); uint64_t temp=n.raw_value()-isn.raw_value(); if(checkpoint==0){ return temp; } uint32_t div=checkpoint/(1ul<<32); uint32_t res=checkpoint%(1ul<<32); if (res<=temp) { temp=(checkpoint-temp-(div-1)*(1ul<<32))<(temp+div*(1ul<<32)-checkpoint)?temp+(div-1)*(1ul<<32):temp+div*(1ul<<32); }else{ temp=(checkpoint-temp-div*(1ul<<32))<(temp+(div+1)*(1ul<<32)-checkpoint)?temp+div*(1ul<<32):temp+(div+1)*(1ul<<32); } return temp; }
//! \brief A 32-bit integer, expressed relative to an arbitrary initial sequence number (ISN) //! \note This is used to express TCP sequence numbers (seqno) and acknowledgment numbers (ackno) classWrappingInt32 { private: //原始32位储存整数 uint32_t _raw_value; //!< The raw 32-bit stored integer
public: //! Construct from a raw 32-bit unsigned integer //显式构造 explicitWrappingInt32(uint32_t raw_value) : _raw_value(raw_value) {} //访问原始存储值 uint32_traw_value()const{ return _raw_value; } //!< Access raw stored value };
//! Transform a 64-bit absolute sequence number (zero-indexed) into a 32-bit relative sequence number //! \param n the absolute sequence number //! \param isn the initial sequence number //! \returns the relative sequence number WrappingInt32 wrap(uint64_t n, WrappingInt32 isn);
//! Transform a 32-bit relative sequence number into a 64-bit absolute sequence number (zero-indexed) //! \param n The relative sequence number //! \param isn The initial sequence number //! \param checkpoint A recent absolute sequence number //! \returns the absolute sequence number that wraps to `n` and is closest to `checkpoint` //! //! \note Each of the two streams of the TCP connection has its own ISN. One stream //! runs from the local TCPSender to the remote TCPReceiver and has one ISN, //! and the other stream runs from the remote TCPSender to the local TCPReceiver and //! has a different ISN. uint64_tunwrap(WrappingInt32 n, WrappingInt32 isn, uint64_t checkpoint);
//! \name Helper functions //!@{
//! \brief The offset of `a` relative to `b` //! \param b the starting point //! \param a the ending point //! \returns the number of increments needed to get from `b` to `a`, //! negative if the number of decrements needed is less than or equal to //! the number of increments inlineint32_toperator-(WrappingInt32 a, WrappingInt32 b) { return a.raw_value() - b.raw_value(); }
//! \brief Whether the two integers are equal. inlinebooloperator==(WrappingInt32 a, WrappingInt32 b) { return a.raw_value() == b.raw_value(); }
//! \brief Whether the two integers are not equal. inlinebooloperator!=(WrappingInt32 a, WrappingInt32 b) { return !(a == b); }
//! \brief Serializes the wrapping integer, `a`. inline std::ostream &operator<<(std::ostream &os, WrappingInt32 a) { return os << a.raw_value(); }
//! \brief The point `b` steps past `a`. inline WrappingInt32 operator+(WrappingInt32 a, uint32_t b) { return WrappingInt32{a.raw_value() + b}; }
//! \brief The point `b` steps before `a`. inline WrappingInt32 operator-(WrappingInt32 a, uint32_t b) { return a + -b; } //!@}
//! \brief The "receiver" part of a TCP implementation.
//! Receives and reassembles segments into a ByteStream, and computes //! the acknowledgment number and window size to advertise back to the //! remote TCPSender. //接收重组segments为 ByteStream,并计算确认号和窗口大小以通告回远程 TCPSender。 classTCPReceiver { //! Our data structure for re-assembling bytes. //我们用于重新组装字节的数据结构。 StreamReassembler _reassembler;
//! The maximum number of bytes we'll store. //容量大小 size_t _capacity; WrappingInt32 ISN; bool syn_flag; public:
//! \brief Construct a TCP receiver //! //! \param capacity the maximum number of bytes that the receiver will //! store in its buffers at any give time. //构造函数,构造一个 TCP 接收器,容量接收器在任何给定时间将存储在其缓冲区中的最大字节数。 TCPReceiver(constsize_t capacity) : _reassembler(capacity), _capacity(capacity),ISN(0) ,syn_flag(0){}
//! \name Accessors to provide feedback to the remote TCPSender //!@{
//! \brief The ackno that should be sent to the peer //! \returns empty if no SYN has been received //! //! This is the beginning of the receiver's window, or in other words, the sequence number //! of the first byte in the stream that the receiver hasn't received. // 如果没有收到 SYN,则应发送给对等方的 ackno 为空 //这是接收器窗口的开始,否则,接收器未接收到的流中第一个字节的序列号。 std::optional<WrappingInt32> ackno()const;
//! \brief The window size that should be sent to the peer //! //! Operationally: the capacity minus the number of bytes that the //! TCPReceiver is holding in its byte stream (those that have been //! reassembled, but not consumed). //! //! Formally: the difference between (a) the sequence number of //! the first byte that falls after the window (and will not be //! accepted by the receiver) and (b) the sequence number of the //! beginning of the window (the ackno). size_twindow_size()const; //!@}
//! \brief number of bytes stored but not yet reassembled size_tunassembled_bytes()const{ return _reassembler.unassembled_bytes(); }
//! \brief handle an inbound segment voidsegment_received(const TCPSegment &seg);