0

Working on a TCP implementation and have encountered the need to cast from a uint64_t to a wrapping uint32_t, but am really not sure how to account for possible overflows.

This image describes the data types. absolute seqno is the uint64_t and goes up to 2^64 - 1(max possible length) while seqno goes up to 2^32 - 1 and then goes back to 0. SYN is a uint32_t representing the starting of seqno.

I'm unsure as to how accounting for overflows must be done; my current conversion implementation is as follows:

uint32_t wrap(uint64_t n, uint32_t syn) {

    if (n < std::pow(2, 32) - syn) {
        return static_cast<uint32_t>(n) + syn;
    }

    return syn;
}

Is there a better, proper way to do this conversion to ensure resetting of seqno regardless of the value of absolute seqno ? Thanks.

LE for clarity: converting 260 to unsigned char should give me 4(when exceeding 255, the "counting" starts again from 0).

beginner420
  • 39
  • 1
  • 7
  • 1
    Unclear what you want to do tbh. Does this help: [Saturating subtract/add for unsigned bytes](https://stackoverflow.com/q/33481295/10147399) – Aykhan Hagverdili Dec 21 '20 at 13:39
  • @AyxanHaqverdili have added an edit with an example. Same logic, but for possible very large numbers that would overflow multiple times. – beginner420 Dec 21 '20 at 14:05
  • Don't use `std::pow` for integers. It's a floating point function. If you want `2^32 - syn` you'd be better off with `(1ul << 32 - syn)` or since signed over/underflow is welldefined, `std::uint32_t(0) - syn` (since 2^32 in an unsigned 32 bit integer will overflow to 0) – JohnFilleau Dec 21 '20 at 16:55

0 Answers0