The only way the buffer can become non-full is when bytes are acknowledged, which can happen only when a packet arrives. Similarly, the transport sink is told an upper limit on the number of bytes it may buffer. In order for the transport layers of two hosts to communicate, they must use the network layer to send packets. The network layer is best-effort, meaning it can drop, reorder, delay, alter, and misroute packets. The crc32.h interface is provided for your convenience.
Reliability also requires the use of sequence numbers.
Either way can work, and people will disagree about which is easier. You need to make sure that sequence numbers don't get reused before they leave the network, which means you need to have enough distinct sequence numbers. Reliability also requires you to heed the warnings in network.h about data types being represented differently on different machines. You can represent the window as a number of packets or as a number of bytes. The easiest way to prevent the transport source from overflowing the transport sink's buffer is to shrink the window size as the buffer fills up, which is typically accomplished by indicating the amount of free buffer space in every ack.