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-2024 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.4.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL TFTP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "tftp/tftp_client.h"
36 #include "tftp/tftp_client_misc.h"
37 #include "debug.h"
38 
39 //Check TCP/IP stack configuration
40 #if (TFTP_CLIENT_SUPPORT == ENABLED)
41 
42 
43 /**
44  * @brief Open connection with the TFTP server
45  * @param[in] context Pointer to the TFTP client context
46  * @return Error code
47  **/
48 
50 {
51  error_t error;
52 
53  //Properly close existing connection
55 
56  //Open a UDP socket
58 
59  //Valid socket?
60  if(context->socket != NULL)
61  {
62  //Associate the socket with the relevant interface
63  error = socketBindToInterface(context->socket, context->interface);
64 
65  //Check status code
66  if(!error)
67  {
68  //Set timeout
70  }
71 
72  //Any error to report?
73  if(error)
74  {
75  //Clean up side effects
77  }
78  }
79  else
80  {
81  //Report an error
82  error = ERROR_OPEN_FAILED;
83  }
84 
85  //Return status code
86  return error;
87 }
88 
89 
90 /**
91  * @brief Close connection with the TFTP server
92  * @param[in] context Pointer to the TFTP client context
93  **/
94 
96 {
97  //Sanity check
98  if(context->socket != NULL)
99  {
100  //Close UDP socket
101  socketClose(context->socket);
102  context->socket = NULL;
103  }
104 }
105 
106 
107 /**
108  * @brief Process TFTP client events
109  * @param[in] context Pointer to the TFTP client context
110  * @return Error code
111  **/
112 
114 {
115  error_t error;
116  systime_t time;
118  uint16_t srcPort;
119 
120  //Wait for an incoming packet
121  error = socketReceiveFrom(context->socket, &srcIpAddr, &srcPort,
122  context->inPacket, TFTP_CLIENT_MAX_PACKET_SIZE, &context->inPacketLen, 0);
123 
124  //Check status code
125  if(error == NO_ERROR)
126  {
127  //Process incoming packet
128  tftpClientProcessPacket(context, &srcIpAddr, srcPort);
129  }
130  else if(error == ERROR_TIMEOUT)
131  {
132 #if (NET_RTOS_SUPPORT == ENABLED)
133  error = NO_ERROR;
134 #else
135  error = ERROR_WOULD_BLOCK;
136 #endif
137  }
138 
139  //Check status code
140  if(error == NO_ERROR || error == ERROR_WOULD_BLOCK)
141  {
142  //Check current state
143  if(context->state == TFTP_CLIENT_STATE_RRQ ||
144  context->state == TFTP_CLIENT_STATE_WRQ ||
145  context->state == TFTP_CLIENT_STATE_DATA ||
146  context->state == TFTP_CLIENT_STATE_ACK ||
148  {
149  //Get current time
150  time = osGetSystemTime();
151 
152  //Check current time
153  if(timeCompare(time, context->timestamp + TFTP_CLIENT_TIMEOUT) >= 0)
154  {
155  //Handle retransmissions
157  {
158  //Retransmit last packet
160 
161  //Save the time at which the packet was sent
162  context->timestamp = osGetSystemTime();
163  //Increment retransmission counter
164  context->retransmitCount++;
165  }
166  else
167  {
168  //Report a timeout error
169  error = ERROR_TIMEOUT;
170  }
171  }
172  }
173  }
174 
175  //Return status code
176  return error;
177 }
178 
179 
180 /**
181  * @brief Process incoming packet
182  * @param[in] context Pointer to the TFTP client context
183  * @param[in] srcIpAddr Source IP address
184  * @param[in] srcPort Source port number
185  **/
186 
188  const IpAddr *srcIpAddr, uint16_t srcPort)
189 {
190  uint16_t opcode;
191 
192  //Check the source IP address of the incoming packet
193  if(!ipCompAddr(srcIpAddr, &context->serverIpAddr))
194  return;
195 
196  //Malformed packet?
197  if(context->inPacketLen < sizeof(uint16_t))
198  return;
199 
200  //Retrieve TFTP packet type
201  opcode = LOAD16BE(context->inPacket);
202 
203  //Data packet received?
204  if(opcode == TFTP_OPCODE_DATA)
205  {
206  //Process DATA packet
207  tftpClientProcessDataPacket(context, srcPort,
208  (TftpDataPacket *) context->inPacket, context->inPacketLen);
209  }
210  //Acknowledgment packet received?
211  else if(opcode == TFTP_OPCODE_ACK)
212  {
213  //Process ACK packet
214  tftpClientProcessAckPacket(context, srcPort,
215  (TftpAckPacket *) context->inPacket, context->inPacketLen);
216  }
217  //Error packet received?
218  else if(opcode == TFTP_OPCODE_ERROR)
219  {
220  //Process ERROR packet
221  tftpClientProcessErrorPacket(context, srcPort,
222  (TftpErrorPacket *) context->inPacket, context->inPacketLen);
223  }
224  //Invalid packet received?
225  else
226  {
227  //Discard incoming packet
228  }
229 }
230 
231 
232 /**
233  * @brief Process incoming DATA packet
234  * @param[in] context Pointer to the TFTP client context
235  * @param[in] srcPort Source port number
236  * @param[in] dataPacket Pointer to the DATA packet
237  * @param[in] length Length of the packet, in bytes
238  **/
239 
241  uint16_t srcPort, const TftpDataPacket *dataPacket, size_t length)
242 {
243  //Debug message
244  TRACE_DEBUG("TFTP Client: DATA packet received (%" PRIuSIZE " bytes)...\r\n",
245  length);
246 
247  //Make sure the length of the DATA packet is acceptable
248  if(length < sizeof(TftpDataPacket))
249  return;
250 
251  //Calculate the length of the data
252  length -= sizeof(TftpDataPacket);
253 
254  //Debug message
255  TRACE_DEBUG(" Opcode = %" PRIu16 "\r\n", ntohs(dataPacket->opcode));
256  TRACE_DEBUG(" Block = %" PRIu16 "\r\n", ntohs(dataPacket->block));
257 
258  //Check current state
259  if(context->state == TFTP_CLIENT_STATE_RRQ)
260  {
261  //Check block number
262  if(ntohs(dataPacket->block) == context->block)
263  {
264  //Save the TID chosen by the server
265  context->serverTid = srcPort;
266 
267  //A valid DATA packet has been received
268  context->state = TFTP_CLIENT_STATE_DATA;
269 
270  //Save the length of the DATA packet
271  context->inDataLen = length;
272  context->inDataPos = 0;
273  }
274  }
275  else if(context->state == TFTP_CLIENT_STATE_ACK)
276  {
277  //The host should make sure that the source TID matches the value
278  //that was agreed
279  if(srcPort == context->serverTid)
280  {
281  //Check block number
282  if(ntohs(dataPacket->block) == context->block)
283  {
284  //A valid DATA packet has been received
285  context->state = TFTP_CLIENT_STATE_DATA;
286 
287  //Save the length of the DATA packet
288  context->inDataLen = length;
289  context->inDataPos = 0;
290  }
291  else
292  {
293  //Retransmit ACK packet
295  }
296  }
297  }
298 }
299 
300 
301 /**
302  * @brief Process incoming ACK packet
303  * @param[in] context Pointer to the TFTP client context
304  * @param[in] srcPort Source port number
305  * @param[in] ackPacket Pointer to the ACK packet
306  * @param[in] length Length of the packet, in bytes
307  **/
308 
310  uint16_t srcPort, const TftpAckPacket *ackPacket, size_t length)
311 {
312  //Debug message
313  TRACE_DEBUG("TFTP Client: ACK packet received (%" PRIuSIZE " bytes)...\r\n",
314  length);
315 
316  //Make sure the length of the ACK packet is acceptable
317  if(length < sizeof(TftpAckPacket))
318  return;
319 
320  //Debug message
321  TRACE_DEBUG(" Opcode = %" PRIu16 "\r\n", ntohs(ackPacket->opcode));
322  TRACE_DEBUG(" Block = %" PRIu16 "\r\n", ntohs(ackPacket->block));
323 
324  //Check current state
325  if(context->state == TFTP_CLIENT_STATE_WRQ)
326  {
327  //Check block number
328  if(ntohs(ackPacket->block) == context->block)
329  {
330  //Save the TID chosen by the server
331  context->serverTid = srcPort;
332 
333  //A valid ACK packet has been received
334  context->state = TFTP_CLIENT_STATE_ACK;
335 
336  //Flush the output data buffer
337  context->outDataLen = 0;
338  }
339  }
340  else if(context->state == TFTP_CLIENT_STATE_DATA)
341  {
342  //The host should make sure that the source TID matches the value
343  //that was agreed
344  if(srcPort == context->serverTid)
345  {
346  //Make sure the ACK is not a duplicate
347  if(ntohs(ackPacket->block) == context->block)
348  {
349  //A valid ACK packet has been received
350  context->state = TFTP_CLIENT_STATE_ACK;
351 
352  //Flush the output data buffer
353  context->outDataLen = 0;
354  }
355  else
356  {
357  //Implementations must never resend the current DATA packet on
358  //receipt of a duplicate ACK (refer to RFC 1123, section 4.2.3.1)
359  }
360  }
361  }
362  else if(context->state == TFTP_CLIENT_STATE_LAST_DATA)
363  {
364  //The host should make sure that the source TID matches the value
365  //that was agreed
366  if(srcPort == context->serverTid)
367  {
368  //Make sure the ACK is not a duplicate
369  if(ntohs(ackPacket->block) == context->block)
370  {
371  //Normal termination of the transfer
373 
374  //Flush the output data buffer
375  context->outDataLen = 0;
376  }
377  else
378  {
379  //Implementations must never resend the current DATA packet on
380  //receipt of a duplicate ACK (refer to RFC 1123, section 4.2.3.1)
381  }
382  }
383  }
384 }
385 
386 
387 /**
388  * @brief Process incoming ERROR packet
389  * @param[in] context Pointer to the TFTP client context
390  * @param[in] srcPort Source port number
391  * @param[in] errorPacket Pointer to the ERROR packet
392  * @param[in] length Length of the packet, in bytes
393  **/
394 
396  uint16_t srcPort, const TftpErrorPacket *errorPacket, size_t length)
397 {
398  //Debug message
399  TRACE_DEBUG("TFTP Client: ERROR packet received (%" PRIuSIZE " bytes)...\r\n",
400  length);
401 
402  //Make sure the length of the ERROR packet is acceptable
403  if(length < sizeof(TftpErrorPacket))
404  return;
405 
406  //Debug message
407  TRACE_DEBUG(" Opcode = %" PRIu16 "\r\n", ntohs(errorPacket->opcode));
408  TRACE_DEBUG(" Error Code = %" PRIu16 "\r\n", ntohs(errorPacket->errorCode));
409 
410  //Compute the length of the error message
411  length -= sizeof(TftpErrorPacket);
412 
413  //Make sure the error message is terminated with a zero byte
414  if(length > 1 && errorPacket->errorMsg[length - 1] == '\0')
415  {
416  //Debug message
417  TRACE_DEBUG(" Error Msg = %s\r\n", errorPacket->errorMsg);
418  }
419 
420  //Report an error
421  context->state = TFTP_CLIENT_STATE_ERROR;
422 }
423 
424 
425 /**
426  * @brief Send RRQ packet
427  * @param[in] context Pointer to the TFTP client context
428  * @param[in] filename NULL-terminated string specifying the filename
429  * @param[in] mode NULL-terminated string specifying the transfer mode
430  * @return Error code
431  **/
432 
434  const char_t *filename, const char_t *mode)
435 {
436  error_t error;
437  size_t m;
438  size_t n;
439  TftpRrqPacket *rrqPacket;
440 
441  //Retrieve the length of the filename
442  m = osStrlen(filename);
443  //Retrieve the length of the transfer mode
444  n = osStrlen(mode);
445 
446  //Check the length of the filename
447  if((m + n) > TFTP_CLIENT_BLOCK_SIZE)
449 
450  //Point to the buffer where to format the packet
451  rrqPacket = (TftpRrqPacket *) context->outPacket;
452 
453  //Format RRQ packet
454  rrqPacket->opcode = HTONS(TFTP_OPCODE_RRQ);
455  osStrcpy(rrqPacket->filename, filename);
456  osStrcpy(rrqPacket->filename + m + 1, mode);
457 
458  //Compute the length of the RRQ packet
459  context->outPacketLen = sizeof(TftpRrqPacket) + n + m + 2;
460 
461  //Debug message
462  TRACE_DEBUG("TFTP Client: Sending RRQ packet (%" PRIuSIZE " bytes)...\r\n", context->outPacketLen);
463  TRACE_DEBUG(" Opcode = %u\r\n", ntohs(rrqPacket->opcode));
464  TRACE_DEBUG(" Filename = %s\r\n", rrqPacket->filename);
465  TRACE_DEBUG(" Mode = %s\r\n", mode);
466 
467  //Send RRQ packet
468  error = socketSendTo(context->socket, &context->serverIpAddr,
469  context->serverPort, context->outPacket, context->outPacketLen, NULL, 0);
470 
471  //Save the time at which the packet was sent
472  context->timestamp = osGetSystemTime();
473  //Reset retransmission counter
474  context->retransmitCount = 0;
475 
476  //Return status code
477  return error;
478 }
479 
480 
481 /**
482  * @brief Send WRQ packet
483  * @param[in] context Pointer to the TFTP client context
484  * @param[in] filename NULL-terminated string specifying the filename
485  * @param[in] mode NULL-terminated string specifying the transfer mode
486  * @return Error code
487  **/
488 
490  const char_t *filename, const char_t *mode)
491 {
492  error_t error;
493  size_t m;
494  size_t n;
495  TftpWrqPacket *wrqPacket;
496 
497  //Retrieve the length of the filename
498  m = osStrlen(filename);
499  //Retrieve the length of the transfer mode
500  n = osStrlen(mode);
501 
502  //Check the length of the filename
503  if((m + n) > TFTP_CLIENT_BLOCK_SIZE)
505 
506  //Point to the buffer where to format the packet
507  wrqPacket = (TftpWrqPacket *) context->outPacket;
508 
509  //Format WRQ packet
510  wrqPacket->opcode = HTONS(TFTP_OPCODE_WRQ);
511  osStrcpy(wrqPacket->filename, filename);
512  osStrcpy(wrqPacket->filename + m + 1, mode);
513 
514  //Compute the length of the WRQ packet
515  context->outPacketLen = sizeof(TftpRrqPacket) + n + m + 2;
516 
517  //Debug message
518  TRACE_DEBUG("TFTP Client: Sending WRQ packet (%" PRIuSIZE " bytes)...\r\n", context->outPacketLen);
519  TRACE_DEBUG(" Opcode = %u\r\n", ntohs(wrqPacket->opcode));
520  TRACE_DEBUG(" Filename = %s\r\n", wrqPacket->filename);
521  TRACE_DEBUG(" Mode = %s\r\n", mode);
522 
523  //Send WRQ packet
524  error = socketSendTo(context->socket, &context->serverIpAddr,
525  context->serverPort, context->outPacket, context->outPacketLen, NULL, 0);
526 
527  //Save the time at which the packet was sent
528  context->timestamp = osGetSystemTime();
529  //Reset retransmission counter
530  context->retransmitCount = 0;
531 
532  //Return status code
533  return error;
534 }
535 
536 
537 /**
538  * @brief Send DATA packet
539  * @param[in] context Pointer to the TFTP client context
540  * @return Error code
541  **/
542 
544 {
545  error_t error;
546  TftpDataPacket *dataPacket;
547 
548  //Point to the buffer where to format the packet
549  dataPacket = (TftpDataPacket *) context->outPacket;
550 
551  //Format DATA packet
552  dataPacket->opcode = HTONS(TFTP_OPCODE_DATA);
553  dataPacket->block = htons(context->block);
554 
555  //Compute the length of the DATA packet
556  context->outPacketLen = sizeof(TftpDataPacket) + context->outDataLen;
557 
558  //Debug message
559  TRACE_DEBUG("TFTP Client: Sending DATA packet (%" PRIuSIZE " bytes)...\r\n", context->outPacketLen);
560  TRACE_DEBUG(" Opcode = %" PRIu16 "\r\n", ntohs(dataPacket->opcode));
561  TRACE_DEBUG(" Block = %" PRIu16 "\r\n", ntohs(dataPacket->block));
562 
563  //Send DATA packet
564  error = socketSendTo(context->socket, &context->serverIpAddr,
565  context->serverTid, context->outPacket, context->outPacketLen, NULL, 0);
566 
567  //Save the time at which the packet was sent
568  context->timestamp = osGetSystemTime();
569  //Reset retransmission counter
570  context->retransmitCount = 0;
571 
572  //Return status code
573  return error;
574 }
575 
576 
577 /**
578  * @brief Send ACK packet
579  * @param[in] context Pointer to the TFTP client context
580  * @return Error code
581  **/
582 
584 {
585  error_t error;
586  TftpAckPacket *ackPacket;
587 
588  //Point to the buffer where to format the packet
589  ackPacket = (TftpAckPacket *) context->outPacket;
590 
591  //Format ACK packet
592  ackPacket->opcode = HTONS(TFTP_OPCODE_ACK);
593  ackPacket->block = htons(context->block);
594 
595  //Length of the ACK packet
596  context->outPacketLen = sizeof(TftpAckPacket);
597 
598  //Debug message
599  TRACE_DEBUG("TFTP Client: Sending ACK packet (%" PRIuSIZE " bytes)...\r\n", context->outPacketLen);
600  TRACE_DEBUG(" Opcode = %" PRIu16 "\r\n", ntohs(ackPacket->opcode));
601  TRACE_DEBUG(" Block = %" PRIu16 "\r\n", ntohs(ackPacket->block));
602 
603  //Send ACK packet
604  error = socketSendTo(context->socket, &context->serverIpAddr,
605  context->serverTid, context->outPacket, context->outPacketLen, NULL, 0);
606 
607  //Save the time at which the packet was sent
608  context->timestamp = osGetSystemTime();
609  //Reset retransmission counter
610  context->retransmitCount = 0;
611 
612  //Return status code
613  return error;
614 }
615 
616 
617 /**
618  * @brief Send ERROR packet
619  * @param[in] context Pointer to the TFTP client context
620  * @param[in] errorCode Integer indicating the nature of the error
621  * @param[in] errorMsg Error message intended for human consumption
622  * @return Error code
623  **/
624 
626  uint16_t errorCode, const char_t *errorMsg)
627 {
628  error_t error;
629  TftpErrorPacket *errorPacket;
630 
631  //Check the length of the error message
634 
635  //Point to the buffer where to format the packet
636  errorPacket = (TftpErrorPacket *) context->outPacket;
637 
638  //Format ERROR packet
639  errorPacket->opcode = HTONS(TFTP_OPCODE_ERROR);
640  errorPacket->errorCode = htons(errorCode);
641 
642  //Copy error message
643  osStrcpy(errorPacket->errorMsg, errorMsg);
644 
645  //Compute the length of the ERROR packet
646  context->outPacketLen = sizeof(TftpErrorPacket) + osStrlen(errorMsg) + 1;
647 
648  //Debug message
649  TRACE_DEBUG("TFTP Client: Sending ERROR packet (%" PRIuSIZE " bytes)...\r\n", context->outPacketLen);
650  TRACE_DEBUG(" Opcode = %" PRIu16 "\r\n", ntohs(errorPacket->opcode));
651  TRACE_DEBUG(" Error Code = %" PRIu16 "\r\n", ntohs(errorPacket->errorCode));
652  TRACE_DEBUG(" Error Msg = %s\r\n", errorPacket->errorMsg);
653 
654  //Send ERROR packet
655  error = socketSendTo(context->socket, &context->serverIpAddr,
656  context->serverTid, context->outPacket, context->outPacketLen, NULL, 0);
657 
658  //Save the time at which the packet was sent
659  context->timestamp = osGetSystemTime();
660  //Reset retransmission counter
661  context->retransmitCount = 0;
662 
663  //Return status code
664  return error;
665 }
666 
667 
668 /**
669  * @brief Retransmit the last packet
670  * @param[in] context Pointer to the TFTP client context
671  * @return Error code
672  **/
673 
675 {
676  error_t error;
677  uint16_t destPort;
678 
679  //Select the relevant destination port
680  if(context->state == TFTP_CLIENT_STATE_RRQ ||
681  context->state == TFTP_CLIENT_STATE_WRQ)
682  {
683  //The client sends its initial request to the known TID 69
684  destPort = context->serverPort;
685  }
686  else
687  {
688  //Under normal operation, the client uses the TID chosen by the server
689  destPort = context->serverTid;
690  }
691 
692  //Debug message
693  TRACE_DEBUG("TFTP Client: Retransmitting packet (%" PRIuSIZE " bytes)...\r\n",
694  context->outPacketLen);
695 
696  //Retransmit the last packet
697  error = socketSendTo(context->socket, &context->serverIpAddr,
698  destPort, context->outPacket, context->outPacketLen, NULL, 0);
699 
700  //Return status code
701  return error;
702 }
703 
704 #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:2062
@ 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:340
#define osStrlen(s)
Definition: os_port.h:165
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:1714
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:368
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:107
@ ERROR_TIMEOUT
Definition: error.h:95
char char_t
Definition: compiler_port.h:48
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:1507
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
@ 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:207
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