lab2 done right
This commit is contained in:
parent
752d0d5a4a
commit
ca1e263114
@ -10,8 +10,37 @@ void DUMMY_CODE(Targs &&.../* unused */) {}
|
||||
|
||||
using namespace std;
|
||||
|
||||
void TCPReceiver::segment_received(const TCPSegment &seg) { DUMMY_CODE(seg); }
|
||||
void TCPReceiver::segment_received(const TCPSegment &seg) {
|
||||
if (seg.header().syn) {
|
||||
_syn = true;
|
||||
// there's no way to know whether connection has been established from bytestream status,
|
||||
// so a special member is needed
|
||||
_isn = seg.header().seqno;
|
||||
}
|
||||
if (!_syn)
|
||||
return; // abandon packets before SYN
|
||||
uint64_t checkpoint = stream_out().bytes_written() ? stream_out().bytes_written() - 1 : 0;
|
||||
// special case for initial SYN
|
||||
uint64_t abs_seqno = unwrap(seg.header().seqno, _isn, checkpoint);
|
||||
// In your TCP implementation, you’ll use the index of the last reassembled byte as the checkpoint.
|
||||
// So, the bytes_written-1 (Stream Indices) should be this value
|
||||
// Watch out for the case when no bytes have been assembled
|
||||
if (abs_seqno == 0 && !seg.header().syn)
|
||||
return;
|
||||
// assertion: when abs_seqno is 0, this packet must be syn
|
||||
uint64_t index = abs_seqno - (abs_seqno ? 1 : 0); // special case for SYN&FIN
|
||||
_reassembler.push_substring(seg.payload().copy(), index, seg.header().fin);
|
||||
_abs_ackno = stream_out().bytes_written() + 1 + (stream_out().input_ended() ? 1 : 0);
|
||||
_ackno = wrap(_abs_ackno, _isn);
|
||||
}
|
||||
|
||||
optional<WrappingInt32> TCPReceiver::ackno() const { return {}; }
|
||||
optional<WrappingInt32> TCPReceiver::ackno() const {
|
||||
if (_syn)
|
||||
return _ackno;
|
||||
return {};
|
||||
}
|
||||
|
||||
size_t TCPReceiver::window_size() const { return {}; }
|
||||
size_t TCPReceiver::window_size() const {
|
||||
// capacity minus the number of bytes holding in the byte stream
|
||||
return _capacity - stream_out().buffer_size();
|
||||
}
|
||||
|
||||
@ -19,9 +19,10 @@ class TCPReceiver {
|
||||
|
||||
//! The maximum number of bytes we'll store.
|
||||
size_t _capacity;
|
||||
WrappingInt32 _seqno{0};
|
||||
WrappingInt32 _isn{0};
|
||||
WrappingInt32 _ackno{0};
|
||||
bool _is_start{};
|
||||
uint64_t _abs_ackno{0};
|
||||
bool _syn{};
|
||||
|
||||
public:
|
||||
//! \brief Construct a TCP receiver
|
||||
|
||||
@ -47,4 +47,10 @@ uint64_t unwrap(WrappingInt32 n, WrappingInt32 isn, uint64_t checkpoint) {
|
||||
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.
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user