From 7d3124fb4ba8c2c18b1c2d992c01167a13386815 Mon Sep 17 00:00:00 2001 From: "Joseph C. Lehner" Date: Wed, 26 Jul 2023 11:38:39 +0200 Subject: [PATCH] Drain NMRP rx buffer before TFTP upload More debug log spam --- nmrp.c | 29 +++++++++++++++++++++++++++++ nmrpd.h | 3 +++ tftp.c | 11 ++++++++--- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/nmrp.c b/nmrp.c index 230c7b5..ae69a8c 100644 --- a/nmrp.c +++ b/nmrp.c @@ -348,6 +348,32 @@ static void sigh(int sig) g_interrupted = 1; } +static void nmrp_drain(void* arg) +{ + // between nmrpflash sending the TFTP WRQ packet, and the router + // responding with ACK(0)/OACK, some devices send extraneous + // CONF_REQ and/or TFTP_UL_REQ packets. + // + // we drain the NMRP receive buffer here, otherwise it might seem + // as if these packets arrived *after* the TFTP upload. + + struct nmrp_pkt rx; + int i = 0; + + while (pkt_recv((struct ethsock*)arg, &rx) == 0) { + if (rx.msg.code != NMRP_C_CONF_REQ && rx.msg.code != NMRP_C_TFTP_UL_REQ) { + if (verbosity > 1) { + printf("Drained unexpected packet type %s\n", msg_code_str(rx.msg.code)); + } + } + ++i; + } + + if (verbosity > 1) { + printf("Drained %d packet(s) from rx buffer\n", i); + } +} + static const char *spinner = "\\|/-"; int nmrp_do(struct nmrpd_args *args) @@ -564,6 +590,9 @@ int nmrp_do(struct nmrpd_args *args) ulreqs = 0; ka_reqs = 0; + args->on_tftp_ack0_callback = &nmrp_drain; + args->on_tftp_ack0_arg = sock; + while (!g_interrupted) { if (expect != NMRP_C_NONE && rx.msg.code != expect) { fprintf(stderr, "Received %s while waiting for %s!\n", diff --git a/nmrpd.h b/nmrpd.h index f7ca57b..3aaebe0 100644 --- a/nmrpd.h +++ b/nmrpd.h @@ -112,6 +112,9 @@ struct nmrpd_args { uint16_t port; const char *region; off_t offset; + + void (*on_tftp_ack0_callback)(void*); + void* on_tftp_ack0_arg; }; const char *leafname(const char *path); diff --git a/tftp.c b/tftp.c index 5ce15db..c30042d 100644 --- a/tftp.c +++ b/tftp.c @@ -328,8 +328,8 @@ ssize_t tftp_put(struct nmrpd_args *args) char rx[2048], tx[2048]; const char *file_remote = args->file_remote; char *val, *end; - bool rollover; - const unsigned rx_timeout = MAX(args->rx_timeout / (args->blind ? 50 : 5), 2000); + bool rollover, tftp_ack0_callback_called; + const unsigned rx_timeout = MIN(args->rx_timeout / (args->blind ? 50 : 5), 2000); const unsigned max_timeouts = args->blind ? 3 : 5; #ifndef NMRPFLASH_WINDOWS int enabled = 1; @@ -393,7 +393,6 @@ ssize_t tftp_put(struct nmrpd_args *args) } if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) != 0) { - printf("errno=%d\n", errno); sock_perror("bind"); goto cleanup; } @@ -415,6 +414,7 @@ ssize_t tftp_put(struct nmrpd_args *args) rollover = false; /* Not really, but this way the loop sends our WRQ before receiving */ timeouts = 1; + tftp_ack0_callback_called = false; pkt_mkwrq(tx, file_remote, TFTP_BLKSIZE); @@ -440,6 +440,11 @@ ssize_t tftp_put(struct nmrpd_args *args) } } } + + if (!ackblock && args->on_tftp_ack0_callback && !tftp_ack0_callback_called) { + args->on_tftp_ack0_callback(args->on_tftp_ack0_arg); + tftp_ack0_callback_called = true; + } } if (timeouts || ackblock == block) {