A1. Read the TCP chapters in textbook, and RFC 793. Make sure to clearly
understand how TCP works before you start. Then study the code and try to
understand how the files (especially those realted to mysock and transport layer)
are structured and connected with each other. Note that the only file you need
to modify is
transport.c, and that
all the functions you may use.
A2. Because it expects to find the ACK field set to 0 (even though the ACK flag is not set on the first SYN packet). It is a quirk of the reference solution.
A3. You can change anything you like in transport.c, except for code inside "#ifdef FIXED_INITNUM." (Grading depends on this staying the same!) You can add any other functions or data types that you wish.
A4. Yes. There is nothing stopping us from testing your receiver against another student's transmitter, or against our own transport layer which specifically does X as a test case for your code.
A5. When the application requests that a mysocket is closed (via myclose()), your transport layer will receive a 'close requested event' from stcp_wait_for_event(); this is your cue to send a FIN segment once all pending data has been successfully transmitted. When you receive a FIN from the peer, and all expected data from the peer has been passed up to the application, you indicate that subsequent myread()s should return zero by calling stcp_fin_received().
A6. No. You can assume that the implied payload length: len_from_stcp_network_recv - stcp_data_offset is correct and that no bytes at the tail end of the packet were lost, i.e. datagram transmission is all or nothing. If your buffer can fit it, you always get the whole datagram from the network layer as transmitted by the sender.
A7. Several reasons. For one, it actually makes things easier in the long run. If there was just one process/thread, how would the transport layer get control of the CPU when a timeout occurs or when a packet comes in? The only way to do this would be with signals. The signal model can work, but is much harder to debug with regards to things like race conditions. You have to explicitly deal with reentrancy issues and critical sections.
The event-driven model we have allows the transport layer to sleep until an interesting event happens. In some respects, this is a simpler model than you'd face in implementing a real TCP stack.
The second reason is that it abstracts the socket layer away from the transport layer. The layer you are writing is much more like a protocol stack that would actually fit into the operating system: you have a defined interface above you and below you, and you don't really need to know or care what the user processes above you are doing.
A8. It is the system time at which the function should return, if there is no pending event of interest. It is not a time interval relative to the current time, i.e. it has the same origin as functions like gettimeofday(2). Note that timespec used by stcp_wait_for_event() has a tv_nsec (nanosecond) field as opposed to the more common timeval which has a tv_usec (microsecond) field. If you use gettimeofday(2) to obtain the current time you will need to convert between the two struct types
A9. Anything declared in stcp_api.h or transport.h is fair game. You should not use any other methods or data types defined by the mysock implementation. You should study stcp_api.h in detail as these will be the primary (re: only) network/application I/O functions that transport.c will use. For example, you must use stcp_network_send() and stcp_network_recv() to send and receive packets from the network.
A10. No. This does add some complexity into the assignment. You're not required to deal with it. We're not going to test your programs to transfer 4 gigabytes of data :-) But keep in mind this happens in real TCP.
A11. In modern computer architectures, the internal representation of a struct with a bunch of fields might contain some bytes of inner padding to align the fields with the word boundaries (this is done for performance reasons). However when you try to send this data, you do not want to send unnecessary padding, because the receiving machine might have a different internal representation.
So, what you want the compiler to do is to eliminate any padding, and to pack all fields back to back, so that the internal and the network representation are the same (except perhaps for byte ordering). This is the role of the PACK directives.
A12. Nope. Although this would be handled by 'real' TCP, because of the way we simulate the underlying unreliable network layer, the specifics of how ports are assigned depends on the underlying network layer in the mysock implementation. Consequently, the mysock layer takes care of assigning ports and setting these values accordingly. You do not have to handle demultiplexing of connections.
A13. No, but you will probably still want to do other error checking in the header.
A14. You can use the function gettimeofday(2). You cannot use any function from the real-time library (-lrt).
A15. You should only read as much data from the application as you're planning on sending. Let the rest of it sit there until you're ready to send it (i.e. an ACK opens up the receive window again).
Note that the transmitter has to keep track of the sender window, based on the 3072-byte receiver window, the current ACK sequence number and the outstanding amount of un-acknowledged data, in order to know how much to send.
A16. No. You have to look at both the start and end of the segment. For example, if the ACK sequence number is 1000 (1000 is the next byte you expect), and a segment comes in with a sequence number of 800 and a length of 300 (i.e. ends at 1099), then you have to keep the data from 1000 to 1099. A similar case exists at the end of the receive window.
A17. Assuming you are using the virtual machine, it is because you need to add "labpc-virtual.cs.princeton.edu" to the end of the first line of the hosts file (/etc/hosts)