tftp_client_misc.c
Go to the documentation of this file.
1 /**
2  * @file tftp_client_misc.c
3  * @brief Helper functions for TFTP client
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.5.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL TFTP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "tftp/tftp_client.h"
37 #include "tftp/tftp_client_misc.h"
38 #include "debug.h"
39 
40 //Check TCP/IP stack configuration
41 #if (TFTP_CLIENT_SUPPORT == ENABLED)
42 
43 
44 /**
45  * @brief Open connection with the TFTP server
46  * @param[in] context Pointer to the TFTP client context
47  * @return Error code
48  **/
49 
51 {
52  error_t error;
53 
54  //Properly close existing connection
56 
57  //Open a UDP socket
59 
60  //Valid socket?
61  if(context->socket != NULL)
62  {
63  //Associate the socket with the relevant interface
64  error = socketBindToInterface(context->socket, context->interface);
65 
66  //Check status code
67  if(!error)
68  {
69  //Set timeout
71  }
72 
73  //Any error to report?
74  if(error)
75  {
76  //Clean up side effects
78  }
79  }
80  else
81  {
82  //Report an error
83  error = ERROR_OPEN_FAILED;
84  }
85 
86  //Return status code
87  return error;
88 }
89 
90 
91 /**
92  * @brief Close connection with the TFTP server
93  * @param[in] context Pointer to the TFTP client context
94  **/
95 
97 {
98  //Sanity check
99  if(context->socket != NULL)
100  {
101  //Close UDP socket
102  socketClose(context->socket);
103  context->socket = NULL;
104  }
105 }
106 
107 
108 /**
109  * @brief Process TFTP client events
110  * @param[in] context Pointer to the TFTP client context
111  * @return Error code
112  **/
113 
115 {
116  error_t error;
117  systime_t time;
119  uint16_t srcPort;
120 
121  //Wait for an incoming packet
122  error = socketReceiveFrom(context->socket, &srcIpAddr, &srcPort,
123  context->inPacket, TFTP_CLIENT_MAX_PACKET_SIZE, &context->inPacketLen, 0);
124 
125  //Check status code
126  if(error == NO_ERROR)
127  {
128  //Process incoming packet
129  tftpClientProcessPacket(context, &srcIpAddr, srcPort);
130  }
131  else if(error == ERROR_TIMEOUT)
132  {
133 #if (NET_RTOS_SUPPORT == ENABLED)
134  error = NO_ERROR;
135 #else
136  error = ERROR_WOULD_BLOCK;
137 #endif
138  }
139 
140  //Check status code
141  if(error == NO_ERROR || error == ERROR_WOULD_BLOCK)
142  {
143  //Check current state
144  if(context->state == TFTP_CLIENT_STATE_RRQ ||
145  context->state == TFTP_CLIENT_STATE_WRQ ||
146  context->state == TFTP_CLIENT_STATE_DATA ||
147  context->state == TFTP_CLIENT_STATE_ACK ||
149  {
150  //Get current time
151  time = osGetSystemTime();
152 
153  //Check current time
154  if(timeCompare(time, context->timestamp + TFTP_CLIENT_TIMEOUT) >= 0)
155  {
156  //Handle retransmissions
158  {
159  //Retransmit last packet
161 
162  //Save the time at which the packet was sent
163  context->timestamp = osGetSystemTime();
164  //Increment retransmission counter
165  context->retransmitCount++;
166  }
167  else
168  {
169  //Report a timeout error
170  error = ERROR_TIMEOUT;
171  }
172  }
173  }
174  }
175 
176  //Return status code
177  return error;
178 }
179 
180 
181 /**
182  * @brief Process incoming packet
183  * @param[in] context Pointer to the TFTP client context
184  * @param[in] srcIpAddr Source IP address
185  * @param[in] srcPort Source port number
186  **/
187 
189  const IpAddr *srcIpAddr, uint16_t srcPort)
190 {
191  uint16_t opcode;
192 
193  //Check the source IP address of the incoming packet
194  if(!ipCompAddr(srcIpAddr, &context->serverIpAddr))
195  return;
196 
197  //Malformed packet?
198  if(context->inPacketLen < sizeof(uint16_t))
199  return;
200 
201  //Retrieve TFTP packet type
202  opcode = LOAD16BE(context->inPacket);
203 
204  //Data packet received?
205  if(opcode == TFTP_OPCODE_DATA)
206  {
207  //Process DATA packet
208  tftpClientProcessDataPacket(context, srcPort,
209  (TftpDataPacket *) context->inPacket, context->inPacketLen);
210  }
211  //Acknowledgment packet received?
212  else if(opcode == TFTP_OPCODE_ACK)
213  {
214  //Process ACK packet
215  tftpClientProcessAckPacket(context, srcPort,
216  (TftpAckPacket *) context->inPacket, context->inPacketLen);
217  }
218  //Error packet received?
219  else if(opcode == TFTP_OPCODE_ERROR)
220  {
221  //Process ERROR packet
222  tftpClientProcessErrorPacket(context, srcPort,
223  (TftpErrorPacket *) context->inPacket, context->inPacketLen);
224  }
225  //Invalid packet received?
226  else
227  {
228  //Discard incoming packet
229  }
230 }
231 
232 
233 /**
234  * @brief Process incoming DATA packet
235  * @param[in] context Pointer to the TFTP client context
236  * @param[in] srcPort Source port number
237  * @param[in] dataPacket Pointer to the DATA packet
238  * @param[in] length Length of the packet, in bytes
239  **/
240 
242  uint16_t srcPort, const TftpDataPacket *dataPacket, size_t length)
243 {
244  //Debug message
245  TRACE_DEBUG("TFTP Client: DATA packet received (%" PRIuSIZE " bytes)...\r\n",
246  length);
247 
248  //Make sure the length of the DATA packet is acceptable
249  if(length < sizeof(TftpDataPacket))
250  return;
251 
252  //Calculate the length of the data
253  length -= sizeof(TftpDataPacket);
254 
255  //Debug message
256  TRACE_DEBUG(" Opcode = %" PRIu16 "\r\n", ntohs(dataPacket->opcode));
257  TRACE_DEBUG(" Block = %" PRIu16 "\r\n", ntohs(dataPacket->block));
258 
259  //Check current state
260  if(context->state == TFTP_CLIENT_STATE_RRQ)
261  {
262  //Check block number
263  if(ntohs(dataPacket->block) == context->block)
264  {
265  //Save the TID chosen by the server
266  context->serverTid = srcPort;
267 
268  //A valid DATA packet has been received
269  context->state = TFTP_CLIENT_STATE_DATA;
270 
271  //Save the length of the DATA packet
272  context->inDataLen = length;
273  context->inDataPos = 0;
274  }
275  }
276  else if(context->state == TFTP_CLIENT_STATE_ACK)
277  {
278  //The host should make sure that the source TID matches the value
279  //that was agreed
280  if(srcPort == context->serverTid)
281  {
282  //Check block number
283  if(ntohs(dataPacket->block) == context->block)
284  {
285  //A valid DATA packet has been received
286  context->state = TFTP_CLIENT_STATE_DATA;
287 
288  //Save the length of the DATA packet
289  context->inDataLen = length;
290  context->inDataPos = 0;
291  }
292  else
293  {
294  //Retransmit ACK packet
296  }
297  }
298  }
299 }
300 
301 
302 /**
303  * @brief Process incoming ACK packet
304  * @param[in] context Pointer to the TFTP client context
305  * @param[in] srcPort Source port number
306  * @param[in] ackPacket Pointer to the ACK packet
307  * @param[in] length Length of the packet, in bytes
308  **/
309 
311  uint16_t srcPort, const TftpAckPacket *ackPacket, size_t length)
312 {
313  //Debug message
314  TRACE_DEBUG("TFTP Client: ACK packet received (%" PRIuSIZE " bytes)...\r\n",
315  length);
316 
317  //Make sure the length of the ACK packet is acceptable
318  if(length < sizeof(TftpAckPacket))
319  return;
320 
321  //Debug message
322  TRACE_DEBUG(" Opcode = %" PRIu16 "\r\n", ntohs(ackPacket->opcode));
323  TRACE_DEBUG(" Block = %" PRIu16 "\r\n", ntohs(ackPacket->block));
324 
325  //Check current state
326  if(context->state == TFTP_CLIENT_STATE_WRQ)
327  {
328  //Check block number
329  if(ntohs(ackPacket->block) == context->block)
330  {
331  //Save the TID chosen by the server
332  context->serverTid = srcPort;
333 
334  //A valid ACK packet has been received
335  context->state = TFTP_CLIENT_STATE_ACK;
336 
337  //Flush the output data buffer
338  context->outDataLen = 0;
339  }
340  }
341  else if(context->state == TFTP_CLIENT_STATE_DATA)
342  {
343  //The host should make sure that the source TID matches the value
344  //that was agreed
345  if(srcPort == context->serverTid)
346  {
347  //Make sure the ACK is not a duplicate
348  if(ntohs(ackPacket->block) == context->block)
349  {
350  //A valid ACK packet has been received
351  context->state = TFTP_CLIENT_STATE_ACK;
352 
353  //Flush the output data buffer
354  context->outDataLen = 0;
355  }
356  else
357  {
358  //Implementations must never resend the current DATA packet on
359  //receipt of a duplicate ACK (refer to RFC 1123, section 4.2.3.1)
360  }
361  }
362  }
363  else if(context->state == TFTP_CLIENT_STATE_LAST_DATA)
364  {
365  //The host should make sure that the source TID matches the value
366  //that was agreed
367  if(srcPort == context->serverTid)
368  {
369  //Make sure the ACK is not a duplicate
370  if(ntohs(ackPacket->block) == context->block)
371  {
372  //Normal termination of the transfer
374 
375  //Flush the output data buffer
376  context->outDataLen = 0;
377  }
378  else
379  {
380  //Implementations must never resend the current DATA packet on
381  //receipt of a duplicate ACK (refer to RFC 1123, section 4.2.3.1)
382  }
383  }
384  }
385 }
386 
387 
388 /**
389  * @brief Process incoming ERROR packet
390  * @param[in] context Pointer to the TFTP client context
391  * @param[in] srcPort Source port number
392  * @param[in] errorPacket Pointer to the ERROR packet
393  * @param[in] length Length of the packet, in bytes
394  **/
395 
397  uint16_t srcPort, const TftpErrorPacket *errorPacket, size_t length)
398 {
399  //Debug message
400  TRACE_DEBUG("TFTP Client: ERROR packet received (%" PRIuSIZE " bytes)...\r\n",
401  length);
402 
403  //Make sure the length of the ERROR packet is acceptable
404  if(length < sizeof(TftpErrorPacket))
405  return;
406 
407  //Debug message
408  TRACE_DEBUG(" Opcode = %" PRIu16 "\r\n", ntohs(errorPacket->opcode));
409  TRACE_DEBUG(" Error Code = %" PRIu16 "\r\n", ntohs(errorPacket->errorCode));
410 
411  //Compute the length of the error message
412  length -= sizeof(TftpErrorPacket);
413 
414  //Make sure the error message is terminated with a zero byte
415  if(length > 1 && errorPacket->errorMsg[length - 1] == '\0')
416  {
417  //Debug message
418  TRACE_DEBUG(" Error Msg = %s\r\n", errorPacket->errorMsg);
419  }
420 
421  //Report an error
422  context->state = TFTP_CLIENT_STATE_ERROR;
423 }
424 
425 
426 /**
427  * @brief Send RRQ packet
428  * @param[in] context Pointer to the TFTP client context
429  * @param[in] filename NULL-terminated string specifying the filename
430  * @param[in] mode NULL-terminated string specifying the transfer mode
431  * @return Error code
432  **/
433 
435  const char_t *filename, const char_t *mode)
436 {
437  error_t error;
438  size_t m;
439  size_t n;
440  TftpRrqPacket *rrqPacket;
441 
442  //Retrieve the length of the filename
443  m = osStrlen(filename);
444  //Retrieve the length of the transfer mode
445  n = osStrlen(mode);
446 
447  //Check the length of the filename
448  if((m + n) > TFTP_CLIENT_BLOCK_SIZE)
450 
451  //Point to the buffer where to format the packet
452  rrqPacket = (TftpRrqPacket *) context->outPacket;
453 
454  //Format RRQ packet
455  rrqPacket->opcode = HTONS(TFTP_OPCODE_RRQ);
456  osStrcpy(rrqPacket->filename, filename);
457  osStrcpy(rrqPacket->filename + m + 1, mode);
458 
459  //Compute the length of the RRQ packet
460  context->outPacketLen = sizeof(TftpRrqPacket) + n + m + 2;
461 
462  //Debug message
463  TRACE_DEBUG("TFTP Client: Sending RRQ packet (%" PRIuSIZE " bytes)...\r\n", context->outPacketLen);
464  TRACE_DEBUG(" Opcode = %u\r\n", ntohs(rrqPacket->opcode));
465  TRACE_DEBUG(" Filename = %s\r\n", rrqPacket->filename);
466  TRACE_DEBUG(" Mode = %s\r\n", mode);
467 
468  //Send RRQ packet
469  error = socketSendTo(context->socket, &context->serverIpAddr,
470  context->serverPort, context->outPacket, context->outPacketLen, NULL, 0);
471 
472  //Save the time at which the packet was sent
473  context->timestamp = osGetSystemTime();
474  //Reset retransmission counter
475  context->retransmitCount = 0;
476 
477  //Return status code
478  return error;
479 }
480 
481 
482 /**
483  * @brief Send WRQ packet
484  * @param[in] context Pointer to the TFTP client context
485  * @param[in] filename NULL-terminated string specifying the filename
486  * @param[in] mode NULL-terminated string specifying the transfer mode
487  * @return Error code
488  **/
489 
491  const char_t *filename, const char_t *mode)
492 {
493  error_t error;
494  size_t m;
495  size_t n;
496  TftpWrqPacket *wrqPacket;
497 
498  //Retrieve the length of the filename
499  m = osStrlen(filename);
500  //Retrieve the length of the transfer mode
501  n = osStrlen(mode);
502 
503  //Check the length of the filename
504  if((m + n) > TFTP_CLIENT_BLOCK_SIZE)
506 
507  //Point to the buffer where to format the packet
508  wrqPacket = (TftpWrqPacket *) context->outPacket;
509 
510  //Format WRQ packet
511  wrqPacket->opcode = HTONS(TFTP_OPCODE_WRQ);
512  osStrcpy(wrqPacket->filename, filename);
513  osStrcpy(wrqPacket->filename + m + 1, mode);
514 
515  //Compute the length of the WRQ packet
516  context->outPacketLen = sizeof(TftpRrqPacket) + n + m + 2;
517 
518  //Debug message
519  TRACE_DEBUG("TFTP Client: Sending WRQ packet (%" PRIuSIZE " bytes)...\r\n", context->outPacketLen);
520  TRACE_DEBUG(" Opcode = %u\r\n", ntohs(wrqPacket->opcode));
521  TRACE_DEBUG(" Filename = %s\r\n", wrqPacket->filename);
522  TRACE_DEBUG(" Mode = %s\r\n", mode);
523 
524  //Send WRQ packet
525  error = socketSendTo(context->socket, &context->serverIpAddr,
526  context->serverPort, context->outPacket, context->outPacketLen, NULL, 0);
527 
528  //Save the time at which the packet was sent
529  context->timestamp = osGetSystemTime();
530  //Reset retransmission counter
531  context->retransmitCount = 0;
532 
533  //Return status code
534  return error;
535 }
536 
537 
538 /**
539  * @brief Send DATA packet
540  * @param[in] context Pointer to the TFTP client context
541  * @return Error code
542  **/
543 
545 {
546  error_t error;
547  TftpDataPacket *dataPacket;
548 
549  //Point to the buffer where to format the packet
550  dataPacket = (TftpDataPacket *) context->outPacket;
551 
552  //Format DATA packet
553  dataPacket->opcode = HTONS(TFTP_OPCODE_DATA);
554  dataPacket->block = htons(context->block);
555 
556  //Compute the length of the DATA packet
557  context->outPacketLen = sizeof(TftpDataPacket) + context->outDataLen;
558 
559  //Debug message
560  TRACE_DEBUG("TFTP Client: Sending DATA packet (%" PRIuSIZE " bytes)...\r\n", context->outPacketLen);
561  TRACE_DEBUG(" Opcode = %" PRIu16 "\r\n", ntohs(dataPacket->opcode));
562  TRACE_DEBUG(" Block = %" PRIu16 "\r\n", ntohs(dataPacket->block));
563 
564  //Send DATA packet
565  error = socketSendTo(context->socket, &context->serverIpAddr,
566  context->serverTid, context->outPacket, context->outPacketLen, NULL, 0);
567 
568  //Save the time at which the packet was sent
569  context->timestamp = osGetSystemTime();
570  //Reset retransmission counter
571  context->retransmitCount = 0;
572 
573  //Return status code
574  return error;
575 }
576 
577 
578 /**
579  * @brief Send ACK packet
580  * @param[in] context Pointer to the TFTP client context
581  * @return Error code
582  **/
583 
585 {
586  error_t error;
587  TftpAckPacket *ackPacket;
588 
589  //Point to the buffer where to format the packet
590  ackPacket = (TftpAckPacket *) context->outPacket;
591 
592  //Format ACK packet
593  ackPacket->opcode = HTONS(TFTP_OPCODE_ACK);
594  ackPacket->block = htons(context->block);
595 
596  //Length of the ACK packet
597  context->outPacketLen = sizeof(TftpAckPacket);
598 
599  //Debug message
600  TRACE_DEBUG("TFTP Client: Sending ACK packet (%" PRIuSIZE " bytes)...\r\n", context->outPacketLen);
601  TRACE_DEBUG(" Opcode = %" PRIu16 "\r\n", ntohs(ackPacket->opcode));
602  TRACE_DEBUG(" Block = %" PRIu16 "\r\n", ntohs(ackPacket->block));
603 
604  //Send ACK packet
605  error = socketSendTo(context->socket, &context->serverIpAddr,
606  context->serverTid, context->outPacket, context->outPacketLen, NULL, 0);
607 
608  //Save the time at which the packet was sent
609  context->timestamp = osGetSystemTime();
610  //Reset retransmission counter
611  context->retransmitCount = 0;
612 
613  //Return status code
614  return error;
615 }
616 
617 
618 /**
619  * @brief Send ERROR packet
620  * @param[in] context Pointer to the TFTP client context
621  * @param[in] errorCode Integer indicating the nature of the error
622  * @param[in] errorMsg Error message intended for human consumption
623  * @return Error code
624  **/
625 
627  uint16_t errorCode, const char_t *errorMsg)
628 {
629  error_t error;
630  TftpErrorPacket *errorPacket;
631 
632  //Check the length of the error message
635 
636  //Point to the buffer where to format the packet
637  errorPacket = (TftpErrorPacket *) context->outPacket;
638 
639  //Format ERROR packet
640  errorPacket->opcode = HTONS(TFTP_OPCODE_ERROR);
641  errorPacket->errorCode = htons(errorCode);
642 
643  //Copy error message
644  osStrcpy(errorPacket->errorMsg, errorMsg);
645 
646  //Compute the length of the ERROR packet
647  context->outPacketLen = sizeof(TftpErrorPacket) + osStrlen(errorMsg) + 1;
648 
649  //Debug message
650  TRACE_DEBUG("TFTP Client: Sending ERROR packet (%" PRIuSIZE " bytes)...\r\n", context->outPacketLen);
651  TRACE_DEBUG(" Opcode = %" PRIu16 "\r\n", ntohs(errorPacket->opcode));
652  TRACE_DEBUG(" Error Code = %" PRIu16 "\r\n", ntohs(errorPacket->errorCode));
653  TRACE_DEBUG(" Error Msg = %s\r\n", errorPacket->errorMsg);
654 
655  //Send ERROR packet
656  error = socketSendTo(context->socket, &context->serverIpAddr,
657  context->serverTid, context->outPacket, context->outPacketLen, NULL, 0);
658 
659  //Save the time at which the packet was sent
660  context->timestamp = osGetSystemTime();
661  //Reset retransmission counter
662  context->retransmitCount = 0;
663 
664  //Return status code
665  return error;
666 }
667 
668 
669 /**
670  * @brief Retransmit the last packet
671  * @param[in] context Pointer to the TFTP client context
672  * @return Error code
673  **/
674 
676 {
677  error_t error;
678  uint16_t destPort;
679 
680  //Select the relevant destination port
681  if(context->state == TFTP_CLIENT_STATE_RRQ ||
682  context->state == TFTP_CLIENT_STATE_WRQ)
683  {
684  //The client sends its initial request to the known TID 69
685  destPort = context->serverPort;
686  }
687  else
688  {
689  //Under normal operation, the client uses the TID chosen by the server
690  destPort = context->serverTid;
691  }
692 
693  //Debug message
694  TRACE_DEBUG("TFTP Client: Retransmitting packet (%" PRIuSIZE " bytes)...\r\n",
695  context->outPacketLen);
696 
697  //Retransmit the last packet
698  error = socketSendTo(context->socket, &context->serverIpAddr,
699  destPort, context->outPacket, context->outPacketLen, NULL, 0);
700 
701  //Return status code
702  return error;
703 }
704 
705 #endif
char_t errorMsg[]
Definition: tftp_common.h:139
#define htons(value)
Definition: cpu_endian.h:413
@ SOCKET_IP_PROTO_UDP
Definition: socket.h:108
uint8_t opcode
Definition: dns_common.h:188
void tftpClientProcessPacket(TftpClientContext *context, const IpAddr *srcIpAddr, uint16_t srcPort)
Process incoming packet.
uint8_t outPacket[TFTP_CLIENT_MAX_PACKET_SIZE]
Outgoing TFTP packet.
Definition: tftp_client.h:143
@ ERROR_WOULD_BLOCK
Definition: error.h:96
IP network address.
Definition: ip.h:90
error_t tftpClientSendDataPacket(TftpClientContext *context)
Send DATA packet.
error_t tftpClientSendErrorPacket(TftpClientContext *context, uint16_t errorCode, const char_t *errorMsg)
Send ERROR packet.
void socketClose(Socket *socket)
Close an existing socket.
Definition: socket.c:2067
@ TFTP_CLIENT_STATE_COMPLETE
Definition: tftp_client.h:119
TftpErrorPacket
Definition: tftp_common.h:140
void tftpClientProcessDataPacket(TftpClientContext *context, uint16_t srcPort, const TftpDataPacket *dataPacket, size_t length)
Process incoming DATA packet.
@ TFTP_OPCODE_ACK
Acknowledgment.
Definition: tftp_common.h:55
@ SOCKET_TYPE_DGRAM
Definition: socket.h:93
@ TFTP_OPCODE_WRQ
Write request.
Definition: tftp_common.h:53
error_t tftpClientSendWrqPacket(TftpClientContext *context, const char_t *filename, const char_t *mode)
Send WRQ packet.
#define TFTP_CLIENT_MAX_RETRIES
Definition: tftp_client.h:54
uint16_t destPort
Definition: tcp.h:347
#define osStrlen(s)
Definition: os_port.h:168
Ipv4Addr srcIpAddr
Definition: ipcp.h:79
uint16_t errorCode
Definition: tftp_common.h:138
#define TFTP_CLIENT_TIMEOUT
Definition: tftp_client.h:61
size_t inPacketLen
Length of the outgoing packet.
Definition: tftp_client.h:140
void tftpClientCloseConnection(TftpClientContext *context)
Close connection with the TFTP server.
#define timeCompare(t1, t2)
Definition: os_port.h:40
TFTP client context.
Definition: tftp_client.h:129
error_t tftpClientOpenConnection(TftpClientContext *context)
Open connection with the TFTP server.
@ ERROR_OPEN_FAILED
Definition: error.h:75
@ TFTP_OPCODE_ERROR
Error.
Definition: tftp_common.h:56
TftpRrqPacket
Definition: tftp_common.h:94
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
TftpWrqPacket
Definition: tftp_common.h:105
error_t tftpClientProcessEvents(TftpClientContext *context)
Process TFTP client events.
error_t
Error codes.
Definition: error.h:43
bool_t ipCompAddr(const IpAddr *ipAddr1, const IpAddr *ipAddr2)
Compare IP addresses.
Definition: ip.c:317
void tftpClientProcessAckPacket(TftpClientContext *context, uint16_t srcPort, const TftpAckPacket *ackPacket, size_t length)
Process incoming ACK packet.
uint16_t serverTid
Definition: tftp_client.h:133
@ TFTP_CLIENT_STATE_WRQ
Definition: tftp_client.h:115
#define TFTP_CLIENT_TICK_INTERVAL
Definition: tftp_client.h:47
error_t socketReceiveFrom(Socket *socket, IpAddr *srcIpAddr, uint16_t *srcPort, void *data, size_t size, size_t *received, uint_t flags)
Receive a datagram from a connectionless socket.
Definition: socket.c:1719
char_t filename[]
Definition: tftp_common.h:93
systime_t timestamp
Time stamp to manage retransmissions.
Definition: tftp_client.h:137
@ TFTP_OPCODE_DATA
Data.
Definition: tftp_common.h:54
TFTP client.
void tftpClientProcessErrorPacket(TftpClientContext *context, uint16_t srcPort, const TftpErrorPacket *errorPacket, size_t length)
Process incoming ERROR packet.
uint8_t length
Definition: tcp.h:375
Socket * socketOpen(uint_t type, uint_t protocol)
Create a socket (UDP or TCP)
Definition: socket.c:125
TftpAckPacket
Definition: tftp_common.h:128
#define TFTP_CLIENT_BLOCK_SIZE
Definition: tftp_client.h:75
#define socketBindToInterface
Definition: net_legacy.h:193
Helper functions for TFTP client.
uint32_t systime_t
System time.
#define ntohs(value)
Definition: cpu_endian.h:421
#define TRACE_DEBUG(...)
Definition: debug.h:119
@ ERROR_TIMEOUT
Definition: error.h:95
char char_t
Definition: compiler_port.h:55
uint32_t time
Socket * socket
Underlying UDP socket.
Definition: tftp_client.h:134
uint8_t m
Definition: ndp.h:304
#define HTONS(value)
Definition: cpu_endian.h:410
uint8_t n
#define TFTP_CLIENT_MAX_PACKET_SIZE
Definition: tftp_client.h:86
@ TFTP_CLIENT_STATE_LAST_DATA
Definition: tftp_client.h:118
uint_t retransmitCount
Retransmission counter.
Definition: tftp_client.h:138
error_t tftpClientRetransmitPacket(TftpClientContext *context)
Retransmit the last packet.
TftpClientState state
TFTP client state.
Definition: tftp_client.h:135
@ TFTP_CLIENT_STATE_ACK
Definition: tftp_client.h:117
error_t socketSendTo(Socket *socket, const IpAddr *destIpAddr, uint16_t destPort, const void *data, size_t length, size_t *written, uint_t flags)
Send a datagram to a specific destination.
Definition: socket.c:1512
size_t outPacketLen
Length of the outgoing packet.
Definition: tftp_client.h:144
@ TFTP_CLIENT_STATE_DATA
Definition: tftp_client.h:116
NetInterface * interface
Underlying network interface.
Definition: tftp_client.h:130
error_t tftpClientSendAckPacket(TftpClientContext *context)
Send ACK packet.
uint16_t block
Block number.
Definition: tftp_client.h:136
uint8_t inPacket[TFTP_CLIENT_MAX_PACKET_SIZE]
Incoming TFTP packet.
Definition: tftp_client.h:139
TftpDataPacket
Definition: tftp_common.h:117
#define PRIuSIZE
#define LOAD16BE(p)
Definition: cpu_endian.h:186
TCP/IP stack core.
@ TFTP_CLIENT_STATE_RRQ
Definition: tftp_client.h:114
error_t tftpClientSendRrqPacket(TftpClientContext *context, const char_t *filename, const char_t *mode)
Send RRQ packet.
#define osStrcpy(s1, s2)
Definition: os_port.h:210
error_t socketSetTimeout(Socket *socket, systime_t timeout)
Set timeout value for blocking operations.
Definition: socket.c:148
@ TFTP_CLIENT_STATE_ERROR
Definition: tftp_client.h:120
@ NO_ERROR
Success.
Definition: error.h:44
uint16_t serverPort
Definition: tftp_client.h:132
Debugging facilities.
systime_t osGetSystemTime(void)
Retrieve system time.
@ TFTP_OPCODE_RRQ
Read request.
Definition: tftp_common.h:52