--- curl-7.21.5_original/lib/tftp.c	2011-10-05 11:06:14.762504739 +0200
+++ curl-7.21.5/lib/tftp.c	2011-10-04 18:03:28.724185668 +0200
@@ -256,19 +256,15 @@
 
     state->max_time = state->start_time+maxtime;
 
-    /* Set per-block timeout to 10% of total */
-    timeout = maxtime/10 ;
+    timeout = maxtime;
 
-    /* Average reposting an ACK after 15 seconds */
-    state->retry_max = (int)timeout/15;
+    /* Average reposting an ACK after 5 seconds */
+    state->retry_max = (int)timeout/5;
   }
   /* But bound the total number */
   if(state->retry_max<3)
     state->retry_max=3;
 
-  if(state->retry_max>50)
-    state->retry_max=50;
-
   /* Compute the re-ACK interval to suit the timeout */
   state->retry_time = (int)(timeout/state->retry_max);
   if(state->retry_time<1)
@@ -598,23 +594,15 @@
   case TFTP_EVENT_DATA:
     /* Is this the block we expect? */
     rblock = getrpacketblock(&state->rpacket);
-    if(NEXT_BLOCKNUM(state->block) != rblock) {
-      /* No, log it, up the retry count and fail if over the limit */
-      infof(data,
-            "Received unexpected DATA packet block %d\n", rblock);
-      state->retries++;
-      if(state->retries > state->retry_max) {
-        failf(data, "tftp_rx: giving up waiting for block %d",
-              NEXT_BLOCKNUM(state->block));
-        return CURLE_TFTP_ILLEGAL;
-      }
-      break;
-    }
-    /* This is the expected block.  Reset counters and ACK it. */
-    state->block = (unsigned short)rblock;
-    state->retries = 0;
+    int exp_block = NEXT_BLOCKNUM(state->block);
+    
+    if (exp_block < rblock)
+        break;
+
+    /* We need to acknowledge blocks that we are waiting for and also the ones that we had already received 
+     * to allow TFTP server use windowing */
     setpacketevent(&state->spacket, TFTP_EVENT_ACK);
-    setpacketblock(&state->spacket, state->block);
+    setpacketblock(&state->spacket, (unsigned short)rblock);
     sbytes = sendto(state->sockfd, (void *)state->spacket.data,
                     4, SEND_4TH_ARG,
                     (struct sockaddr *)&state->remote_addr,
@@ -623,15 +611,30 @@
       failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
       return CURLE_SEND_ERROR;
     }
-
-    /* Check if completed (That is, a less than full packet is received) */
-    if(state->rbytes < (ssize_t)state->blksize+4){
-      state->state = TFTP_STATE_FIN;
+    
+    if (exp_block == rblock) {
+        /* This is the expected block.  Reset counters */
+        state->block = (unsigned short)rblock;
+        state->retries = 0;
+
+        /* Check if completed (That is, a less than full packet is received) */
+        if(state->rbytes < (ssize_t)state->blksize+4){
+          state->state = TFTP_STATE_FIN;
+        }
+        else {
+          state->state = TFTP_STATE_RX;
+        }
+        
+        time(&state->rx_time);
     }
     else {
-      state->state = TFTP_STATE_RX;
+        infof(data,
+            "Received unexpected DATA packet block %d, while waiting for block %d. Block has been acknowledged\n",
+            rblock, exp_block);
+        /* We don't update state->rx_time, because we don't want to delay retransmission of ACK 
+         * for last successfull reception of expected block (its number is (exp_block - 1)) */
     }
-    time(&state->rx_time);
+
     break;
 
   case TFTP_EVENT_OACK:
