"Das U-Boot" Source Tree
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: lwip: tftp: add support of tsize option to client

The TFTP server can report the size of the entire file that is about to
be received in the Transfer Size Option, this is described in RFC 2349.
This functionality is optional and the server may not report tsize in
case it is not supported.

Always send tsize request to the server to query the transfer size,
and in case the server does respond, cache that information locally
in tftp_state.tsize, otherwise cache size 0. Introduce new function
tftp_client_get_tsize() which returns the cached tftp_state.tsize so
clients can determine the transfer size and use it.

Update net/lwip/tftp.c to make use of tftp_client_get_tsize() and
avoid excessive printing of '#' during TFTP transfers in case the
transfer size is reported by the server.

Submitted upstream: https://savannah.nongnu.org/patch/index.php?item_id=10557

Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
Acked-by: Jerome Forissier <jerome.forissier@arm.com>

authored by

Marek Vasut and committed by
Jerome Forissier
337f50ba a28db0f1

+74 -13
+42 -9
lib/lwip/lwip/src/apps/tftp/tftp.c
··· 98 98 int last_pkt; 99 99 u16_t blknum; 100 100 u16_t blksize; 101 + u32_t tsize; 101 102 u8_t retries; 102 103 u8_t mode_write; 103 104 u8_t tftp_mode; ··· 167 168 { 168 169 size_t fname_length = strlen(fname)+1; 169 170 size_t mode_length = strlen(mode)+1; 171 + size_t tsize_length = strlen("tsize")+3; /* "tsize\0\0\0" */ 170 172 size_t blksize_length = 0; 171 173 int blksize = tftp_state.blksize; 172 174 struct pbuf* p; ··· 182 184 } 183 185 } 184 186 185 - p = init_packet(opcode, 0, fname_length + mode_length + blksize_length - 2); 187 + p = init_packet(opcode, 0, fname_length + mode_length + blksize_length + tsize_length - 2); 186 188 if (p == NULL) { 187 189 return ERR_MEM; 188 190 } ··· 190 192 payload = (char*) p->payload; 191 193 MEMCPY(payload+2, fname, fname_length); 192 194 MEMCPY(payload+2+fname_length, mode, mode_length); 195 + sprintf(payload+2+fname_length+mode_length, "tsize%c%u%c", 0, 0, 0); 193 196 if (tftp_state.blksize) 194 - sprintf(payload+2+fname_length+mode_length, "blksize%c%d", 0, tftp_state.blksize); 197 + sprintf(payload+2+fname_length+mode_length+tsize_length, "blksize%c%d", 0, tftp_state.blksize); 195 198 196 199 tftp_state.wait_oack = true; 197 200 ret = udp_sendto(tftp_state.upcb, p, addr, port); ··· 450 453 } 451 454 452 455 blknum = lwip_ntohs(sbuf[1]); 453 - if (tftp_state.blksize && tftp_state.wait_oack) { 456 + if (tftp_state.wait_oack) { 454 457 /* 455 - * Data received while we are expecting an OACK for our blksize option. 458 + * Data received while we are expecting an OACK for our tsize option. 456 459 * This means the server doesn't support it, let's switch back to the 457 460 * default block size. 458 461 */ 459 - tftp_state.blksize = 0; 460 - tftp_state.wait_oack = false; 462 + tftp_state.tsize = 0; 463 + tftp_state.wait_oack = false; 464 + 465 + if (tftp_state.blksize) { 466 + /* 467 + * Data received while we are expecting an OACK for our blksize option. 468 + * This means the server doesn't support it, let's switch back to the 469 + * default block size. 470 + */ 471 + tftp_state.blksize = 0; 472 + tftp_state.wait_oack = false; 473 + } 461 474 } 462 475 if (blknum == tftp_state.blknum) { 463 476 pbuf_remove_header(p, TFTP_HEADER_LENGTH); ··· 527 540 } 528 541 break; 529 542 case PP_HTONS(TFTP_OACK): { 530 - const char *optval = find_option(p, "blksize"); 543 + const char *blksizeoptval = find_option(p, "blksize"); 544 + const char *tsizeoptval = find_option(p, "tsize"); 531 545 u16_t srv_blksize = 0; 546 + u32_t srv_tsize = 0; 532 547 tftp_state.wait_oack = false; 533 - if (optval) { 548 + if (blksizeoptval) { 534 549 if (!tftp_state.blksize) { 535 550 /* We did not request this option */ 536 551 send_error(addr, port, TFTP_ERROR_ILLEGAL_OPERATION, "blksize unexpected"); 537 552 } 538 - srv_blksize = atoi(optval); 553 + srv_blksize = atoi(blksizeoptval); 539 554 if (srv_blksize <= 0 || srv_blksize > tftp_state.blksize) { 540 555 send_error(addr, port, TFTP_ERROR_ILLEGAL_OPERATION, "Invalid blksize"); 541 556 } 542 557 LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: accepting blksize=%d\n", srv_blksize)); 543 558 tftp_state.blksize = srv_blksize; 559 + } 560 + if (tsizeoptval) { 561 + srv_tsize = atoi(tsizeoptval); 562 + if (srv_tsize <= 0) { 563 + srv_tsize = 0; /* tsize is optional */ 564 + } 565 + LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: accepting tsize=%d\n", srv_tsize)); 566 + tftp_state.tsize = srv_tsize; 544 567 } 545 568 send_ack(addr, port, 0); 546 569 break; ··· 653 676 tftp_init_client(const struct tftp_context *ctx) 654 677 { 655 678 return tftp_init_common(LWIP_TFTP_MODE_CLIENT, ctx); 679 + } 680 + 681 + /** @ingroup tftp 682 + * Get the transfer size used by the TFTP client. The server may 683 + * report zero in case this is unsupported. 684 + */ 685 + u32_t 686 + tftp_client_get_tsize(void) 687 + { 688 + return tftp_state.tsize; 656 689 } 657 690 658 691 /** @ingroup tftp
+1
lib/lwip/lwip/src/include/lwip/apps/tftp_client.h
··· 45 45 46 46 err_t tftp_init_client(const struct tftp_context* ctx); 47 47 void tftp_client_set_blksize(u16_t blksize); 48 + u32_t tftp_client_get_tsize(void); 48 49 err_t tftp_get(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, enum tftp_transfer_mode mode); 49 50 err_t tftp_put(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, enum tftp_transfer_mode mode); 50 51
+31 -4
net/lwip/tftp.c
··· 31 31 ulong daddr; 32 32 ulong size; 33 33 ulong block_count; 34 + ulong hash_count; 34 35 ulong start_time; 35 36 enum done_state done; 36 37 }; ··· 49 50 static int store_block(struct tftp_ctx *ctx, void *src, u16_t len) 50 51 { 51 52 ulong store_addr = ctx->daddr; 53 + ulong tftp_tsize; 54 + ulong pos; 52 55 void *ptr; 53 56 54 57 if (CONFIG_IS_ENABLED(LMB)) { ··· 67 70 ctx->daddr += len; 68 71 ctx->size += len; 69 72 ctx->block_count++; 70 - if (ctx->block_count % 10 == 0) { 71 - putc('#'); 72 - if (ctx->block_count % (65 * 10) == 0) 73 - puts("\n\t "); 73 + 74 + tftp_tsize = tftp_client_get_tsize(); 75 + if (tftp_tsize) { 76 + pos = clamp(ctx->size, 0UL, tftp_tsize); 77 + 78 + while (ctx->hash_count < pos * 50 / tftp_tsize) { 79 + putc('#'); 80 + ctx->hash_count++; 81 + } 82 + } else { 83 + if (ctx->block_count % 10 == 0) { 84 + putc('#'); 85 + if (ctx->block_count % (65 * 10) == 0) 86 + puts("\n\t "); 87 + } 74 88 } 75 89 76 90 return 0; ··· 84 98 static void tftp_close(void *handle) 85 99 { 86 100 struct tftp_ctx *ctx = handle; 101 + ulong tftp_tsize; 87 102 ulong elapsed; 88 103 89 104 if (ctx->done == FAILURE || ctx->done == ABORTED) { ··· 91 106 return; 92 107 } 93 108 ctx->done = SUCCESS; 109 + 110 + tftp_tsize = tftp_client_get_tsize(); 111 + if (tftp_tsize) { 112 + /* Print hash marks for the last packet received */ 113 + while (ctx->hash_count < 49) { 114 + putc('#'); 115 + ctx->hash_count++; 116 + } 117 + puts(" "); 118 + print_size(tftp_tsize, ""); 119 + } 94 120 95 121 elapsed = get_timer(ctx->start_time); 96 122 if (elapsed > 0) { ··· 176 202 ctx.done = NOT_DONE; 177 203 ctx.size = 0; 178 204 ctx.block_count = 0; 205 + ctx.hash_count = 0; 179 206 ctx.daddr = addr; 180 207 181 208 printf("Using %s device\n", udev->name);