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:
parent
6307e783d8
commit
df9108e19b
44
lib/tftp.c
44
lib/tftp.c
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user