Hi list,

I'm experiencing problems using libcurl for downloading a file from a TFTP
server. In my environment, network packet drops are very likely to occur.

First, I tried with the (rather old) version 7.21.7, which does not work for me
at all. I always got curl error CURLE_TFTP_ILLEGAL (71) almost right away.
Turning on verbose mode reveals that it failed on the first block ACK packet
that got lost on its way from libcurl to the TFTP server.

Then, I discovered that this kind of problem is already found and fixed in 2011
by Marcin Adamski (See http://curl.haxx.se/mail/lib-2011-10/0044.html ).
So I updated to the most recent libcurl 7.28.0 and tried again. This worked much
better, but still sometimes failed with CURLE_TFTP_ILLEGAL due to timeouts.

After taking a deeper look into the code, I discovered that only some parts of
the patch provided by Marcin Adamski have been adopted. Especially, the nice
idea of immediately re-sending the ACK packet for block X in case we receive
block X data again while waiting for block X+1 was missing. So I created a patch
against v7.28.0 that adds just this (see attachment).

This finally solved my problem. Any chance to get this into the official 
releases?

Best regards,
  Christian
Index: lib/tftp.c
===================================================================
--- lib/tftp.c  (Revision 230290)
+++ lib/tftp.c  (Arbeitskopie)
@@ -591,16 +591,26 @@
   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,

Attachment: signature.asc
Description: OpenPGP digital signature

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html

Reply via email to