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