Commit df9108e1 authored by Dan Fandrich's avatar Dan Fandrich
Browse files

Stop sending retransmitted received blocks up to client

Fixed handling of retransmitted blocks on transmit
Properly aligned data to transmit within packet
Replaced calls to strerror() with Curl_strerror()
parent 6307e783
Loading
Loading
Loading
Loading
+30 −14
Original line number Diff line number Diff line
@@ -86,6 +86,9 @@
/* The last #include file should be: */
#include "memdebug.h"

/* RFC2348 allows the block size to be negotiated, but we don't support that */
#define TFTP_BLOCKSIZE 512

typedef enum {
  TFTP_MODE_NETASCII=0,
  TFTP_MODE_OCTET
@@ -122,7 +125,7 @@ typedef enum {
} tftp_error_t;

typedef struct tftp_packet {
  unsigned char data[516];
  unsigned char data[2 + 2 + TFTP_BLOCKSIZE];
} tftp_packet_t;

typedef struct tftp_state_data {
@@ -274,7 +277,7 @@ static void tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
      /* If we are uploading, send an WRQ */
      setpacketevent(&state->spacket, TFTP_EVENT_WRQ);
      filename = curl_easy_unescape(data, filename, 0, NULL);
      state->conn->upload_fromhere = (char *)&state->spacket.data[2];
      state->conn->upload_fromhere = (char *)&state->spacket.data[4];
      if(data->set.infilesize != -1)
        Curl_pgrsSetUploadSize(data, data->set.infilesize);
    }
@@ -283,7 +286,7 @@ static void tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
      setpacketevent(&state->spacket, TFTP_EVENT_RRQ);
    }
    snprintf((char *)&state->spacket.data[2],
             512,
             TFTP_BLOCKSIZE,
             "%s%c%s%c", filename, '\0',  mode, '\0');
    sbytes = 4 + (int)strlen(filename) + (int)strlen(mode);
    sbytes = sendto(state->sockfd, (void *)&state->spacket,
@@ -291,7 +294,7 @@ static void tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
                    state->conn->ip_addr->ai_addr,
                    state->conn->ip_addr->ai_addrlen);
    if(sbytes < 0) {
      failf(data, "%s\n", strerror(errno));
      failf(data, "%s\n", Curl_strerror(state->conn, errno));
    }
    break;

@@ -359,10 +362,10 @@ static void tftp_rx(tftp_state_data_t *state, tftp_event_t event)
                    (struct sockaddr *)&state->remote_addr,
                    state->remote_addrlen);
    if(sbytes < 0) {
      failf(data, "%s\n", strerror(errno));
      failf(data, "%s\n", Curl_strerror(state->conn, errno));
    }

    /* Check if completed (That is, a less than full packet is recieved) */
    /* Check if completed (That is, a less than full packet is received) */
    if (state->rbytes < (int)sizeof(state->spacket)){
      state->state = TFTP_STATE_FIN;
    }
@@ -387,7 +390,7 @@ static void tftp_rx(tftp_state_data_t *state, tftp_event_t event)
                      state->remote_addrlen);
      /* Check all sbytes were sent */
      if(sbytes<0) {
        failf(data, "%s\n", strerror(errno));
        failf(data, "%s\n", Curl_strerror(state->conn, errno));
      }
    }
    break;
@@ -401,7 +404,7 @@ static void tftp_rx(tftp_state_data_t *state, tftp_event_t event)
    break;
  }
  Curl_pgrsSetDownloadCounter(data,
                              (curl_off_t) state->block*512);
                              (curl_off_t) state->block*TFTP_BLOCKSIZE);
}

/**********************************************************
@@ -433,6 +436,16 @@ static void tftp_tx(tftp_state_data_t *state, tftp_event_t event)
        failf(data, "%s\n",
              "tftp_tx: giving up waiting for block %d ack",
              state->block);
      } else {
	/* Re-send the data packet */
	sbytes = sendto(state->sockfd, (void *)&state->spacket,
			4+state->sbytes, SEND_4TH_ARG,
			(struct sockaddr *)&state->remote_addr,
			state->remote_addrlen);
	/* Check all sbytes were sent */
	if(sbytes<0) {
	  failf(data, "%s\n", Curl_strerror(state->conn, errno));
	}
      }
      return;
    }
@@ -442,18 +455,18 @@ static void tftp_tx(tftp_state_data_t *state, tftp_event_t event)
    state->retries = 0;
    setpacketevent(&state->spacket, TFTP_EVENT_DATA);
    setpacketblock(&state->spacket, state->block);
    if(state->block > 1 && state->sbytes < 512) {
    if(state->block > 1 && state->sbytes < TFTP_BLOCKSIZE) {
      state->state = TFTP_STATE_FIN;
      return;
    }
    Curl_fillreadbuffer(state->conn, 512, &state->sbytes);
    Curl_fillreadbuffer(state->conn, TFTP_BLOCKSIZE, &state->sbytes);
    sbytes = sendto(state->sockfd, (void *)state->spacket.data,
                    4+state->sbytes, SEND_4TH_ARG,
                    (struct sockaddr *)&state->remote_addr,
                    state->remote_addrlen);
    /* Check all sbytes were sent */
    if(sbytes<0) {
      failf(data, "%s\n", strerror(errno));
      failf(data, "%s\n", Curl_strerror(state->conn, errno));
    }
    break;

@@ -474,7 +487,7 @@ static void tftp_tx(tftp_state_data_t *state, tftp_event_t event)
                      state->remote_addrlen);
      /* Check all sbytes were sent */
      if(sbytes<0) {
        failf(data, "%s\n", strerror(errno));
        failf(data, "%s\n", Curl_strerror(state->conn, errno));
      }
    }
    break;
@@ -489,7 +502,7 @@ static void tftp_tx(tftp_state_data_t *state, tftp_event_t event)
  }

  /* Update the progress meter */
  Curl_pgrsSetUploadCounter(data, (curl_off_t) state->block*512);
  Curl_pgrsSetUploadCounter(data, (curl_off_t) state->block*TFTP_BLOCKSIZE);
}

/**********************************************************
@@ -675,9 +688,12 @@ CURLcode Curl_tftp(struct connectdata *conn, bool *done)

	switch(event) {
	case TFTP_EVENT_DATA:
	  if (state->rbytes > 4)
	  /* Don't pass to the client empty or retransmitted packets */
	  if (state->rbytes > 4 && 
	      ((state->block+1) == getrpacketblock(&state->rpacket))) {
	    Curl_client_write(data, CLIENTWRITE_BODY,
			  (char *)&state->rpacket.data[4], state->rbytes-4);
	  }
	  break;
	case TFTP_EVENT_ERROR:
	  state->error = (tftp_error_t)getrpacketblock(&state->rpacket);