46 lines
1.7 KiB
C++
46 lines
1.7 KiB
C++
#include "tcp_receiver.hh"
|
||
|
||
// Dummy implementation of a TCP receiver
|
||
|
||
// 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;
|
||
|
||
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();
|
||
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);
|
||
auto _abs_ackno = stream_out().bytes_written() + 1 + (stream_out().input_ended() ? 1 : 0);
|
||
_ackno = wrap(_abs_ackno, _isn);
|
||
}
|
||
|
||
optional<WrappingInt32> TCPReceiver::ackno() const {
|
||
if (_syn)
|
||
return _ackno;
|
||
return {};
|
||
}
|
||
|
||
size_t TCPReceiver::window_size() const {
|
||
// capacity minus the number of bytes holding in the byte stream
|
||
return _capacity - stream_out().buffer_size();
|
||
}
|