TTFTP Project — Resend Timer Option

by: burt rosenberg
at: university of miami


The original best-effort, packetized data delivery

The Truly Trivial File Transfer Project

Building on the Truly Trivial File Transfer Project, we add timer resends, support for multiple simultaneous transfers, and various error messages, and other clean up.

Specific Objectives

Positive acknowledgements

UDP is a best effort delivery. Packets may be lost, duplicated, or arrive out of order. To create a reliable enough data channel for file transfer, applications build upon the protocol layers offered by UDP/IP. Ttftp uses block numbers in the packets, positive acknowledgements, and a retry-timer to achieve communication reliability.

Following the new protocol recommendations after fixing the Sorcerer's Apprentice Bug (section 4.2.3.1), the sender of data packets is responsible for resending packets. In the case of a read, this is the server (it would be the client that resends if the transfer is a write).

Once the server has sent a data packet, with block number X, it expects to get an acknowledgement from the client with block number X. It discards acknowledgements of any other block number. If after a time-out time it has not received said acknowledgement, it retransmits the data block. Once it receives the correct acknowledgement, the server is done with block number X and will never resend it.

The tftp protocol requires an adaptive timeout value (section 4.2.3.2). The server will monitor roundtrip communication time and set the timeout to some percentage above the value. Ttftp only needs to implement a fixed timeout.

In a retry implementation, after 6 resent data packets, the server sends an error packet with message "timeout" and exits. The client exists whenever it receives an error packet from the server.

Notes on thread implementation of sending retry

Only the server resends, and has timers. The client is not modified, except for linger. In fact, it is the data producer that resends data packets, and the producer can be either the server or the client, depending on whether the transfer is, respectively, a read or a write.

Implementation with the select call.

The perhaps easiest it to replace the socket receive call with a select call, that takes a timeout value. The select call blocks until data is available on the socket, or a timeout occurs. If the timeout occurred, resend the data packet.

Implementation with threads.

Actually I don't suggest this. It's complicated, but you might want to try it anyway.

The the nag program in [repo]/class/examples/nag for an example pattern using threads similar to how I suspect you might for ttftp.

To simplify the interaction between the threads, one thread calls only socket send, the other only socket receive. Therefore, one thread is responsible for hearing the acknowledgements, the other for sending and resending data packets.

The sending thread sends and blocks until notified or until a timeout. The receiving thread notifies the sending thread on each received acknowledgement, unblocking the sending thread thread. On each notification the sending thread identifies the situation and either sends the same packet, sends the next packet, or initiates the end of protocol.

You should consider putting data that is shared between the threads under a mutex to avoid any critical race conditions.

For a good thread reference, see: PThread Tutorial from Lawrence Livermore National Labs.

Concurrent sessions

Read in Beej's how using TCP multiple sessions are supported and implement in your ttftp server. Hint: a fork call in the server; the parent goes back to listening on port 69, the child creates a new socket with an ephemeral port, and handles the rest of this session, then exits.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

Author: Burton Rosenberg
Created: January 18, 2014 as mytftp
Last Update: April 12, 2015 as t-tftpproject-timer.html