From 0ac827848dd1747c8199f338d71a32111bb01fa5 Mon Sep 17 00:00:00 2001
From: Christian Vogt <christian.vogt@loewe-komp.de>
Date: Fri, 16 Nov 2012 15:30:52 +0100
Subject: [PATCH] tftp_rx: handle resends

Re-send ACK for block X in case we receive block X data again while
waiting for block X+1.

Based on an earlier patch by Marcin Adamski.
---
 lib/tftp.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/lib/tftp.c b/lib/tftp.c
index 7202b94d37..832302ed1b 100644
--- a/lib/tftp.c
+++ b/lib/tftp.c
@@ -591,16 +591,26 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
   case TFTP_EVENT_DATA:
     /* Is this the block we expect? */
     rblock = getrpacketblock(&state->rpacket);
-    if(NEXT_BLOCKNUM(state->block) != rblock) {
-      /* No, log it */
+    if( NEXT_BLOCKNUM(state->block) == rblock ) {
+      /* This is the expected block.  Reset counters and ACK it. */
+      state->retries = 0;
+    }
+    else if( state->block == rblock ) {
+      /* This is the last recently received block again. Log it and ACK it again. */
+      infof(data,
+            "Received last DATA packet block %d again.\n",
+            rblock);
+    }
+    else {
+      /* totally unexpected, just log it */
       infof(data,
             "Received unexpected DATA packet block %d, expecting block %d\n",
             rblock, NEXT_BLOCKNUM(state->block));
       break;
     }
-    /* This is the expected block.  Reset counters and ACK it. */
+
+    /* ACK this block. */
     state->block = (unsigned short)rblock;
-    state->retries = 0;
     setpacketevent(&state->spacket, TFTP_EVENT_ACK);
     setpacketblock(&state->spacket, state->block);
     sbytes = sendto(state->sockfd, (void *)state->spacket.data,
-- 
GitLab