mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-12-19 08:21:27 +01:00
lwip: tftp: resend initial request
The TFTP implementation does not resend the initial request if there is no response from the server. Since TFTP is based on UDP, there should be a mechanism to deal with unreliable transmissions at this point, similar to what we have for data packets. Therefore, introduce request retransmission. Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org> CC: Venkatesh Abbarapu <venkatesh.abbarapu@amd.com> CC: Michal Simek <michal.simek@amd.com> CC: Ilias Apalodimas <ilias.apalodimas@linaro.org>
This commit is contained in:
parent
512be89796
commit
46fc565599
@ -79,6 +79,14 @@ enum tftp_error {
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
struct tftp_req {
|
||||||
|
ip_addr_t addr;
|
||||||
|
u16_t port;
|
||||||
|
u16_t opcode;
|
||||||
|
enum tftp_transfer_mode mode;
|
||||||
|
char* fname;
|
||||||
|
};
|
||||||
|
|
||||||
struct tftp_state {
|
struct tftp_state {
|
||||||
const struct tftp_context *ctx;
|
const struct tftp_context *ctx;
|
||||||
void *handle;
|
void *handle;
|
||||||
@ -97,14 +105,33 @@ struct tftp_state {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct tftp_state tftp_state;
|
static struct tftp_state tftp_state;
|
||||||
|
static struct tftp_req tftp_req;
|
||||||
|
|
||||||
static void tftp_tmr(void *arg);
|
static void tftp_tmr(void *arg);
|
||||||
|
static void tftp_req_tmr(void *arg);
|
||||||
|
static const char *mode_to_string(enum tftp_transfer_mode mode);
|
||||||
|
|
||||||
|
static void
|
||||||
|
clear_req(void)
|
||||||
|
{
|
||||||
|
ip_addr_set_any(0, &tftp_req.addr);
|
||||||
|
tftp_req.port = 0;
|
||||||
|
tftp_req.opcode = 0;
|
||||||
|
free(tftp_req.fname);
|
||||||
|
tftp_req.fname = NULL;
|
||||||
|
tftp_req.mode = 0;
|
||||||
|
|
||||||
|
sys_untimeout(tftp_req_tmr, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
close_handle(void)
|
close_handle(void)
|
||||||
{
|
{
|
||||||
|
clear_req();
|
||||||
|
|
||||||
tftp_state.port = 0;
|
tftp_state.port = 0;
|
||||||
ip_addr_set_any(0, &tftp_state.addr);
|
ip_addr_set_any(0, &tftp_state.addr);
|
||||||
|
tftp_state.retries = 0;
|
||||||
|
|
||||||
if (tftp_state.last_data != NULL) {
|
if (tftp_state.last_data != NULL) {
|
||||||
pbuf_free(tftp_state.last_data);
|
pbuf_free(tftp_state.last_data);
|
||||||
@ -209,6 +236,12 @@ send_ack(const ip_addr_t *addr, u16_t port, u16_t blknum)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static err_t
|
||||||
|
resend_request(void)
|
||||||
|
{
|
||||||
|
return send_request(&tftp_req.addr, tftp_req.port, tftp_req.opcode, tftp_req.fname, mode_to_string(tftp_req.mode));
|
||||||
|
}
|
||||||
|
|
||||||
static err_t
|
static err_t
|
||||||
resend_data(const ip_addr_t *addr, u16_t port)
|
resend_data(const ip_addr_t *addr, u16_t port)
|
||||||
{
|
{
|
||||||
@ -336,6 +369,9 @@ tftp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr
|
|||||||
tftp_state.last_pkt = tftp_state.timer;
|
tftp_state.last_pkt = tftp_state.timer;
|
||||||
tftp_state.retries = 0;
|
tftp_state.retries = 0;
|
||||||
|
|
||||||
|
if (tftp_req.fname)
|
||||||
|
clear_req();
|
||||||
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case PP_HTONS(TFTP_RRQ): /* fall through */
|
case PP_HTONS(TFTP_RRQ): /* fall through */
|
||||||
case PP_HTONS(TFTP_WRQ): {
|
case PP_HTONS(TFTP_WRQ): {
|
||||||
@ -542,6 +578,26 @@ tftp_tmr(void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
tftp_req_tmr(void *arg)
|
||||||
|
{
|
||||||
|
if (tftp_state.handle == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sys_timeout(TFTP_TIMER_MSECS, tftp_req_tmr, NULL);
|
||||||
|
|
||||||
|
if (tftp_state.retries < TFTP_MAX_RETRIES) {
|
||||||
|
LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: req timeout, retrying\n"));
|
||||||
|
resend_request();
|
||||||
|
tftp_state.retries++;
|
||||||
|
} else {
|
||||||
|
LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: req timeout\n"));
|
||||||
|
tftp_state.ctx->error(tftp_state.handle, -1, "Request timeout", strlen("Request timeout"));
|
||||||
|
close_handle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize TFTP client/server.
|
* Initialize TFTP client/server.
|
||||||
* @param mode TFTP mode (client/server)
|
* @param mode TFTP mode (client/server)
|
||||||
@ -637,6 +693,20 @@ mode_to_string(enum tftp_transfer_mode mode)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err_t
|
||||||
|
start_send_requests(const ip_addr_t *addr, u16_t port, u16_t opcode, const char* fname, enum tftp_transfer_mode mode)
|
||||||
|
{
|
||||||
|
tftp_req.addr = *addr;
|
||||||
|
tftp_req.port = port;
|
||||||
|
tftp_req.opcode = opcode;
|
||||||
|
tftp_req.fname = strdup(fname);
|
||||||
|
tftp_req.mode = mode;
|
||||||
|
if (!tftp_req.fname)
|
||||||
|
return ERR_MEM;
|
||||||
|
sys_timeout(TFTP_TIMER_MSECS, tftp_req_tmr, NULL);
|
||||||
|
return resend_request();
|
||||||
|
}
|
||||||
|
|
||||||
err_t
|
err_t
|
||||||
tftp_get(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, enum tftp_transfer_mode mode)
|
tftp_get(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, enum tftp_transfer_mode mode)
|
||||||
{
|
{
|
||||||
@ -647,7 +717,7 @@ tftp_get(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, enu
|
|||||||
tftp_state.handle = handle;
|
tftp_state.handle = handle;
|
||||||
tftp_state.blknum = 1;
|
tftp_state.blknum = 1;
|
||||||
tftp_state.mode_write = 1; /* We want to receive data */
|
tftp_state.mode_write = 1; /* We want to receive data */
|
||||||
return send_request(addr, port, TFTP_RRQ, fname, mode_to_string(mode));
|
return start_send_requests(addr, port, TFTP_RRQ, fname, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
err_t
|
err_t
|
||||||
@ -660,7 +730,7 @@ tftp_put(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, enu
|
|||||||
tftp_state.handle = handle;
|
tftp_state.handle = handle;
|
||||||
tftp_state.blknum = 1;
|
tftp_state.blknum = 1;
|
||||||
tftp_state.mode_write = 0; /* We want to send data */
|
tftp_state.mode_write = 0; /* We want to send data */
|
||||||
return send_request(addr, port, TFTP_WRQ, fname, mode_to_string(mode));
|
return start_send_requests(addr, port, TFTP_WRQ, fname, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* LWIP_UDP */
|
#endif /* LWIP_UDP */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user