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()
This commit is contained in:
Dan Fandrich 2006-05-08 19:41:26 +00:00
parent 6307e783d8
commit df9108e19b

View File

@ -86,6 +86,9 @@
/* The last #include file should be: */ /* The last #include file should be: */
#include "memdebug.h" #include "memdebug.h"
/* RFC2348 allows the block size to be negotiated, but we don't support that */
#define TFTP_BLOCKSIZE 512
typedef enum { typedef enum {
TFTP_MODE_NETASCII=0, TFTP_MODE_NETASCII=0,
TFTP_MODE_OCTET TFTP_MODE_OCTET
@ -122,7 +125,7 @@ typedef enum {
} tftp_error_t; } tftp_error_t;
typedef struct tftp_packet { typedef struct tftp_packet {
unsigned char data[516]; unsigned char data[2 + 2 + TFTP_BLOCKSIZE];
} tftp_packet_t; } tftp_packet_t;
typedef struct tftp_state_data { 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 */ /* If we are uploading, send an WRQ */
setpacketevent(&state->spacket, TFTP_EVENT_WRQ); setpacketevent(&state->spacket, TFTP_EVENT_WRQ);
filename = curl_easy_unescape(data, filename, 0, NULL); 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) if(data->set.infilesize != -1)
Curl_pgrsSetUploadSize(data, data->set.infilesize); 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); setpacketevent(&state->spacket, TFTP_EVENT_RRQ);
} }
snprintf((char *)&state->spacket.data[2], snprintf((char *)&state->spacket.data[2],
512, TFTP_BLOCKSIZE,
"%s%c%s%c", filename, '\0', mode, '\0'); "%s%c%s%c", filename, '\0', mode, '\0');
sbytes = 4 + (int)strlen(filename) + (int)strlen(mode); sbytes = 4 + (int)strlen(filename) + (int)strlen(mode);
sbytes = sendto(state->sockfd, (void *)&state->spacket, 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_addr,
state->conn->ip_addr->ai_addrlen); state->conn->ip_addr->ai_addrlen);
if(sbytes < 0) { if(sbytes < 0) {
failf(data, "%s\n", strerror(errno)); failf(data, "%s\n", Curl_strerror(state->conn, errno));
} }
break; break;
@ -359,10 +362,10 @@ static void tftp_rx(tftp_state_data_t *state, tftp_event_t event)
(struct sockaddr *)&state->remote_addr, (struct sockaddr *)&state->remote_addr,
state->remote_addrlen); state->remote_addrlen);
if(sbytes < 0) { 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)){ if (state->rbytes < (int)sizeof(state->spacket)){
state->state = TFTP_STATE_FIN; 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); state->remote_addrlen);
/* Check all sbytes were sent */ /* Check all sbytes were sent */
if(sbytes<0) { if(sbytes<0) {
failf(data, "%s\n", strerror(errno)); failf(data, "%s\n", Curl_strerror(state->conn, errno));
} }
} }
break; break;
@ -401,7 +404,7 @@ static void tftp_rx(tftp_state_data_t *state, tftp_event_t event)
break; break;
} }
Curl_pgrsSetDownloadCounter(data, 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", failf(data, "%s\n",
"tftp_tx: giving up waiting for block %d ack", "tftp_tx: giving up waiting for block %d ack",
state->block); 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; return;
} }
@ -442,18 +455,18 @@ static void tftp_tx(tftp_state_data_t *state, tftp_event_t event)
state->retries = 0; state->retries = 0;
setpacketevent(&state->spacket, TFTP_EVENT_DATA); setpacketevent(&state->spacket, TFTP_EVENT_DATA);
setpacketblock(&state->spacket, state->block); 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; state->state = TFTP_STATE_FIN;
return; return;
} }
Curl_fillreadbuffer(state->conn, 512, &state->sbytes); Curl_fillreadbuffer(state->conn, TFTP_BLOCKSIZE, &state->sbytes);
sbytes = sendto(state->sockfd, (void *)state->spacket.data, sbytes = sendto(state->sockfd, (void *)state->spacket.data,
4+state->sbytes, SEND_4TH_ARG, 4+state->sbytes, SEND_4TH_ARG,
(struct sockaddr *)&state->remote_addr, (struct sockaddr *)&state->remote_addr,
state->remote_addrlen); state->remote_addrlen);
/* Check all sbytes were sent */ /* Check all sbytes were sent */
if(sbytes<0) { if(sbytes<0) {
failf(data, "%s\n", strerror(errno)); failf(data, "%s\n", Curl_strerror(state->conn, errno));
} }
break; break;
@ -474,7 +487,7 @@ static void tftp_tx(tftp_state_data_t *state, tftp_event_t event)
state->remote_addrlen); state->remote_addrlen);
/* Check all sbytes were sent */ /* Check all sbytes were sent */
if(sbytes<0) { if(sbytes<0) {
failf(data, "%s\n", strerror(errno)); failf(data, "%s\n", Curl_strerror(state->conn, errno));
} }
} }
break; break;
@ -489,7 +502,7 @@ static void tftp_tx(tftp_state_data_t *state, tftp_event_t event)
} }
/* Update the progress meter */ /* 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) { switch(event) {
case TFTP_EVENT_DATA: 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, Curl_client_write(data, CLIENTWRITE_BODY,
(char *)&state->rpacket.data[4], state->rbytes-4); (char *)&state->rpacket.data[4], state->rbytes-4);
}
break; break;
case TFTP_EVENT_ERROR: case TFTP_EVENT_ERROR:
state->error = (tftp_error_t)getrpacketblock(&state->rpacket); state->error = (tftp_error_t)getrpacketblock(&state->rpacket);