This is the mail archive of the ecos-patches@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RedBoot - ACK last packet on TFTP close


Index: redboot/current/ChangeLog
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/ChangeLog,v
retrieving revision 1.105
diff -u -5 -p -r1.105 ChangeLog
--- redboot/current/ChangeLog	14 Apr 2003 16:45:36 -0000	1.105
+++ redboot/current/ChangeLog	18 Apr 2003 13:25:45 -0000
@@ -1,5 +1,10 @@
+2003-04-18  Gary Thomas  <gary at mlbassoc dot 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 at iv dot ro>	
 	
 	* src/load.c:
 	Change #else if to #elif so it compiles when TFTP is disabled. 
 	
Index: redboot/current/src/net/tftp_client.c
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/src/net/tftp_client.c,v
retrieving revision 1.12
diff -u -5 -p -r1.12 tftp_client.c
--- redboot/current/src/net/tftp_client.c	7 Aug 2002 14:42:29 -0000	1.12
+++ redboot/current/src/net/tftp_client.c	18 Apr 2003 13:24:04 -0000
@@ -63,11 +63,11 @@
 // So we remember which ports have been used
 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;
     char data[SEGSIZE+sizeof(struct tftphdr)];
     char *bufp;
@@ -121,10 +121,11 @@ tftp_stream_open(connection_info_t *info
     tftp_stream.avail = 0;
     tftp_stream.actual_len = -1;
     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.
     if (tftp_stream_read(&test_buf, 1, err) == 1) {
         // Back up [rewind] over this datum
@@ -135,13 +136,32 @@ tftp_stream_open(connection_info_t *info
         tftp_stream.open = false;
         return -1; // Couldn't read
     }
 }
 
+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;
 }
 
 int
 tftp_stream_read(char *buf,
@@ -162,20 +182,12 @@ tftp_stream_read(char *buf,
             buf += size;
             tftp_stream.bufp += size;
             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
                 break;
             }
@@ -189,11 +201,16 @@ tftp_stream_read(char *buf,
                     (tftp_stream.last_good_block == 0)) {
                     // Timeout - no data received
                     *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
                         data_len -= 4;  /* Sizeof TFTP header */
                         tftp_stream.avail = tftp_stream.actual_len = data_len;


-- 
------------------------------------------------------------
Gary Thomas                 |
MLB Associates              |  Consulting for the
+1 (970) 229-1963           |    Embedded world
http://www.mlbassoc.com/    |
email: <gary at mlbassoc dot com>  |
gpg: http://www.chez-thomas.org/gary/gpg_key.asc
------------------------------------------------------------


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]