57 lines
2.2 KiB
C++
57 lines
2.2 KiB
C++
#include "wrapping_integers.hh"
|
|
|
|
// Dummy implementation of a 32-bit wrapping integer
|
|
|
|
// For Lab 2, please replace with a real implementation that passes the
|
|
// automated checks run by `make check_lab2`.
|
|
|
|
template <typename... Targs>
|
|
void DUMMY_CODE(Targs &&.../* unused */) {}
|
|
|
|
using namespace std;
|
|
|
|
//! 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) {
|
|
uint32_t result = static_cast<uint32_t>(n) + isn.raw_value();
|
|
return WrappingInt32{result};
|
|
}
|
|
|
|
//! 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.
|
|
#define MODULO (1UL << 32)
|
|
uint64_t unwrap(WrappingInt32 n, WrappingInt32 isn, uint64_t checkpoint) {
|
|
// well, really ulgy impl
|
|
// have to make sure that no overflow happens
|
|
uint64_t tmp = static_cast<uint64_t>(n.raw_value() - isn.raw_value());
|
|
tmp += (checkpoint >> 32) << 32;
|
|
if (tmp > checkpoint) {
|
|
if (tmp < MODULO || tmp - checkpoint < checkpoint - (tmp - MODULO)) {
|
|
return tmp;
|
|
} else {
|
|
return tmp - MODULO;
|
|
}
|
|
} else {
|
|
if (checkpoint - tmp < tmp + MODULO - checkpoint) {
|
|
return tmp;
|
|
} else {
|
|
return tmp + MODULO;
|
|
}
|
|
}
|
|
// actually, here is a tricky edge case:
|
|
// what if two possible unwraps have the same distance to checkpoint?
|
|
// For example, when n=2^16,isn=0,checkpoint=2^32
|
|
// I thought about this, and came up with a possible solution:
|
|
// Mathematically, it is a problem, but in TCP's case, it is okay in that
|
|
// it is impossible that window size reaches 2^16.
|
|
}
|