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