aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Fandrich <dan@coneharvesters.com>2006-05-08 19:41:26 +0000
committerDan Fandrich <dan@coneharvesters.com>2006-05-08 19:41:26 +0000
commitdf9108e19b3287d4a0943c473c2af4f29f9004e1 (patch)
treebcbcb5ada7afdd2f8fcb61984cf86b850686805d
parent6307e783d83835ffaa70fc594b2a08307b2e359b (diff)
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()
-rw-r--r--lib/tftp.c44
1 files changed, 30 insertions, 14 deletions
diff --git a/lib/tftp.c b/lib/tftp.c
index 780cceea5..078dcfd8c 100644
--- a/lib/tftp.c
+++ b/lib/tftp.c
@@ -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);