changeset 952:ff91ad81d086

ACK last packet on close.
author gthomas
date Fri, 18 Apr 2003 13:26:07 +0000
parents 3021b4922c80
children c27a128cb861
files packages/redboot/current/ChangeLog packages/redboot/current/src/net/tftp_client.c
diffstat 2 files changed, 33 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/packages/redboot/current/ChangeLog
+++ b/packages/redboot/current/ChangeLog
@@ -1,3 +1,8 @@
+2003-04-18  Gary Thomas  <gary@mlbassoc.com>
+
+	* src/net/tftp_client.c: Arrange to ACK last good packet when closing.
+	Without this, the host can be left tryint to send that packet forever.
+
 2003-04-14  Jani Monoses  <jani@iv.ro>	
 	
 	* src/load.c:
--- a/packages/redboot/current/src/net/tftp_client.c
+++ b/packages/redboot/current/src/net/tftp_client.c
@@ -65,7 +65,7 @@ static int get_port = 7700;
 
 static struct {
     bool open;
-    int  total_timeouts;
+    int  total_timeouts, packets_received;
     unsigned short last_good_block;
     int  avail, actual_len;
     struct sockaddr_in local_addr, from_addr;
@@ -123,6 +123,7 @@ tftp_stream_open(connection_info_t *info
     tftp_stream.last_good_block = 0;
     tftp_stream.total_timeouts = 0;
     tftp_stream.from_addr.sin_port = 0;
+    tftp_stream.packets_received = 0;
 
     // Try and read the first byte [block] since no errors are
     // reported until then.
@@ -137,9 +138,28 @@ tftp_stream_open(connection_info_t *info
     }
 }
 
+static int
+tftp_ack(int *err)
+{
+    struct tftphdr *hdr = (struct tftphdr *)tftp_stream.data;
+    // ACK last packet so server can shut down
+    if (tftp_stream.packets_received > 0) {
+        hdr->th_opcode = htons(ACK);
+        hdr->th_block = htons(tftp_stream.last_good_block);
+        if (__udp_sendto(tftp_stream.data, 4 /* FIXME */, 
+                         &tftp_stream.from_addr, &tftp_stream.local_addr) < 0) {
+            // Problem sending ACK
+            *err = TFTP_NETERR;
+            return -1;
+        }
+    }
+    return 0;
+}
+
 void
 tftp_stream_close(int *err)
 {
+    tftp_ack(err);
     tftp_stream.open = false;
 }
 
@@ -164,16 +184,8 @@ tftp_stream_read(char *buf,
             tftp_stream.avail -= size;
             total_bytes += size;
         } else {
-            if (tftp_stream.last_good_block != 0) {
-                // Send out the ACK
-                hdr->th_opcode = htons(ACK);
-                hdr->th_block = htons(tftp_stream.last_good_block);
-                if (__udp_sendto(tftp_stream.data, 4 /* FIXME */, 
-                                 &tftp_stream.from_addr, &tftp_stream.local_addr) < 0) {
-                    // Problem sending ACK
-                    *err = TFTP_NETERR;
-                    return -1;
-                }
+            if (tftp_ack(err) < 0) {
+                return -1;
             }
             if ((tftp_stream.actual_len >= 0) && (tftp_stream.actual_len < SEGSIZE)) {
                 // Out of data
@@ -191,7 +203,12 @@ tftp_stream_read(char *buf,
                     *err = TFTP_TIMEOUT;
                     return -1;
                 }
+                // Send out the ACK for the last block - maybe server will retry
+                if (tftp_ack(err) < 0) {
+                    return -1;
+                }
             } else {
+                tftp_stream.packets_received++;
                 if (ntohs(hdr->th_opcode) == DATA) {
                     if (ntohs(hdr->th_block) == (tftp_stream.last_good_block+1)) {
                         // Consume this data