ftp_client.c
Go to the documentation of this file.
1 /**
2  * @file ftp_client.c
3  * @brief FTP client (File Transfer Protocol)
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  * @section Description
26  *
27  * File Transfer Protocol (FTP) is a standard network protocol used to
28  * transfer files from one host to another host over a TCP-based network.
29  * Refer to the following RFCs for complete details:
30  * - RFC 959: File Transfer Protocol (FTP)
31  * - RFC 2428: FTP Extensions for IPv6 and NATs
32  *
33  * @author Oryx Embedded SARL (www.oryx-embedded.com)
34  * @version 1.9.0
35  **/
36 
37 //Switch to the appropriate trace level
38 #define TRACE_LEVEL FTP_TRACE_LEVEL
39 
40 //Dependencies
41 #include <stdlib.h>
42 #include <ctype.h>
43 #include "ftp/ftp_client.h"
45 #include "ftp/ftp_client_misc.h"
46 #include "str.h"
47 #include "error.h"
48 #include "debug.h"
49 
50 //Check TCP/IP stack configuration
51 #if (FTP_CLIENT_SUPPORT == ENABLED)
52 
53 
54 /**
55  * @brief Initialize FTP client context
56  * @param[in] context Pointer to the FTP client context
57  * @return Error code
58  **/
59 
61 {
62 #if (FTP_CLIENT_TLS_SUPPORT == ENABLED)
63  error_t error;
64 #endif
65 
66  //Make sure the FTP client context is valid
67  if(context == NULL)
69 
70  //Clear FTP client context
71  memset(context, 0, sizeof(FtpClientContext));
72 
73 #if (FTP_CLIENT_TLS_SUPPORT == ENABLED)
74  //Initialize TLS session state
75  error = tlsInitSessionState(&context->tlsSession);
76  //Any error to report?
77  if(error)
78  return error;
79 #endif
80 
81  //Initialize FTP client state
82  context->state = FTP_CLIENT_STATE_DISCONNECTED;
83 
84  //Default timeout
85  context->timeout = FTP_CLIENT_DEFAULT_TIMEOUT;
86 
87  //Successful initialization
88  return NO_ERROR;
89 }
90 
91 
92 #if (FTP_CLIENT_TLS_SUPPORT == ENABLED)
93 
94 /**
95  * @brief Register TLS initialization callback function
96  * @param[in] context Pointer to the FTP client context
97  * @param[in] callback TLS initialization callback function
98  * @return Error code
99  **/
100 
102  FtpClientTlsInitCallback callback)
103 {
104  //Check parameters
105  if(context == NULL || callback == NULL)
107 
108  //Save callback function
109  context->tlsInitCallback = callback;
110 
111  //Successful processing
112  return NO_ERROR;
113 }
114 
115 #endif
116 
117 
118 /**
119  * @brief Set communication timeout
120  * @param[in] context Pointer to the FTP client context
121  * @param[in] timeout Timeout value, in milliseconds
122  * @return Error code
123  **/
124 
126 {
127  //Make sure the FTP client context is valid
128  if(context == NULL)
130 
131  //Save timeout value
132  context->timeout = timeout;
133 
134  //Successful processing
135  return NO_ERROR;
136 }
137 
138 
139 /**
140  * @brief Bind the FTP client to a particular network interface
141  * @param[in] context Pointer to the FTP client context
142  * @param[in] interface Network interface to be used
143  * @return Error code
144  **/
145 
147  NetInterface *interface)
148 {
149  //Make sure the FTP client context is valid
150  if(context == NULL)
152 
153  //Explicitly associate the FTP client with the specified interface
154  context->interface = interface;
155 
156  //Successful processing
157  return NO_ERROR;
158 }
159 
160 
161 /**
162  * @brief Establish a connection with the specified FTP server
163  * @param[in] context Pointer to the FTP client context
164  * @param[in] serverIpAddr IP address of the FTP server
165  * @param[in] serverPort Port number
166  * @param[in] mode FTP connection mode
167  * @return Error code
168  **/
169 
171  const IpAddr *serverIpAddr, uint16_t serverPort, uint_t mode)
172 {
173  error_t error;
174 
175  //Check parameters
176  if(context == NULL || serverIpAddr == NULL)
178 
179  //Initialize status code
180  error = NO_ERROR;
181 
182  //Establish connection with the FTP server
183  while(!error)
184  {
185  //Check current state
186  if(context->state == FTP_CLIENT_STATE_DISCONNECTED)
187  {
188  //Save the IP address of the FTP server
189  context->serverIpAddr = *serverIpAddr;
190 
191  //Use passive mode?
192  context->passiveMode = (mode & FTP_MODE_PASSIVE) ? TRUE : FALSE;
193 
194  //Open control socket
195  error = ftpClientOpenConnection(context, &context->controlConnection,
197 
198  //Check status code
199  if(!error)
200  {
201  //Establish TCP connection
203  }
204  }
205  else if(context->state == FTP_CLIENT_STATE_CONNECTING_TCP)
206  {
207  //Establish TCP connection
208  error = socketConnect(context->controlConnection.socket, serverIpAddr,
209  serverPort);
210 
211  //Check status code
212  if(!error)
213  {
214  //Implicit FTPS?
216  {
217  //TLS initialization
218  error = ftpClientOpenSecureConnection(context,
219  &context->controlConnection, FTP_CLIENT_TLS_TX_BUFFER_SIZE,
221 
222  //Check status code
223  if(!error)
224  {
225  //Perform TLS handshake
227  }
228  }
229  else
230  {
231  //Flush buffer
232  context->bufferPos = 0;
233  context->commandLen = 0;
234  context->replyLen = 0;
235 
236  //Wait for the connection greeting reply
238  }
239  }
240  }
241  else if(context->state == FTP_CLIENT_STATE_CONNECTING_TLS)
242  {
243  //Perform TLS handshake
244  error = ftpClientEstablishSecureConnection(&context->controlConnection);
245 
246  //Check status code
247  if(!error)
248  {
249  //Implicit FTPS?
251  {
252  //Flush buffer
253  context->bufferPos = 0;
254  context->commandLen = 0;
255  context->replyLen = 0;
256 
257  //Wait for the connection greeting reply
259  }
260  else
261  {
262  //The FTP client is connected
264  }
265  }
266  }
267  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_1)
268  {
269  //Wait for the connection greeting reply
270  error = ftpClientSendCommand(context);
271 
272  //Check status code
273  if(!error)
274  {
275  //Check FTP response code
276  if(FTP_REPLY_CODE_2YZ(context->replyCode))
277  {
278  //Explicit FTPS?
280  {
281  //Format AUTH TLS command
282  error = ftpClientFormatCommand(context, "AUTH TLS", NULL);
283 
284  //Check status code
285  if(!error)
286  {
287  //Send AUTH TLS command and wait for the server's response
289  }
290  }
291  else
292  {
293  //The FTP client is connected
295  }
296  }
297  else
298  {
299  //Report an error
301  }
302  }
303  }
304  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_2)
305  {
306  //Send AUTH TLS command and wait for the server's response
307  error = ftpClientSendCommand(context);
308 
309  //Check status code
310  if(!error)
311  {
312  //Check FTP response code
313  if(FTP_REPLY_CODE_2YZ(context->replyCode))
314  {
315  //TLS initialization
316  error = ftpClientOpenSecureConnection(context,
317  &context->controlConnection, FTP_CLIENT_TLS_TX_BUFFER_SIZE,
319 
320  //Check status code
321  if(!error)
322  {
323  //Perform TLS handshake
325  }
326  }
327  else
328  {
329  //Report an error
331  }
332  }
333  }
334  else if(context->state == FTP_CLIENT_STATE_CONNECTED)
335  {
336  //The FTP client is connected
337  break;
338  }
339  else
340  {
341  //Invalid state
342  error = ERROR_WRONG_STATE;
343  }
344  }
345 
346  //Check status code
347  if(error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
348  {
349  //Check whether the timeout has elapsed
350  error = ftpClientCheckTimeout(context);
351  }
352 
353  //Failed to establish connection with the FTP server?
354  if(error != NO_ERROR && error != ERROR_WOULD_BLOCK)
355  {
356  //Clean up side effects
357  ftpClientCloseConnection(&context->controlConnection);
358  //Update FTP client state
360  }
361 
362  //Return status code
363  return error;
364 }
365 
366 
367 /**
368  * @brief Login to the FTP server using the provided user name and password
369  * @param[in] context Pointer to the FTP client context
370  * @param[in] username NULL-terminated string containing the user name
371  * @param[in] password NULL-terminated string containing the user's password
372  * @return Error code
373  **/
374 
375 error_t ftpClientLogin(FtpClientContext *context, const char_t *username,
376  const char_t *password)
377 {
378  //The USER, PASS and ACCT commands specify access control identifiers
379  return ftpClientLoginEx(context, username, password, "");
380 }
381 
382 
383 /**
384  * @brief Login to the FTP server using user name, password and account
385  * @param[in] context Pointer to the FTP client context
386  * @param[in] username NULL-terminated string containing the user name
387  * @param[in] password NULL-terminated string containing the user's password
388  * @param[in] account NULL-terminated string containing the user's account
389  * @return Error code
390  **/
391 
393  const char_t *password, const char_t *account)
394 {
395  error_t error;
396 
397  //Check parameters
398  if(context == NULL || username == NULL || password == NULL || account == NULL)
400 
401  //Initialize status code
402  error = NO_ERROR;
403 
404  //Execute FTP command sequence
405  while(!error)
406  {
407  //Check current state
408  if(context->state == FTP_CLIENT_STATE_CONNECTED)
409  {
410  //Format USER command
411  error = ftpClientFormatCommand(context, "USER", username);
412 
413  //Check status code
414  if(!error)
415  {
416  //Send USER command and wait for the server's response
418  }
419  }
420  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_1)
421  {
422  //Send USER command and wait for the server's response
423  error = ftpClientSendCommand(context);
424 
425  //Check status code
426  if(!error)
427  {
428  //Check FTP response code
429  if(FTP_REPLY_CODE_2YZ(context->replyCode))
430  {
431  //Update FTP client state
433  //Successful user identification
434  break;
435  }
436  else if(FTP_REPLY_CODE_3YZ(context->replyCode))
437  {
438  //Format PASS command
439  error = ftpClientFormatCommand(context, "PASS", password);
440 
441  //Check status code
442  if(!error)
443  {
444  //Send PASS command and wait for the server's response
446  }
447  }
448  else
449  {
450  //Update FTP client state
452  //Report an error
454  }
455  }
456  }
457  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_2)
458  {
459  //Send PASS command and wait for the server's response
460  error = ftpClientSendCommand(context);
461 
462  //Check status code
463  if(!error)
464  {
465  //Check FTP response code
466  if(FTP_REPLY_CODE_2YZ(context->replyCode))
467  {
468  //Update FTP client state
470  //Successful user identification
471  break;
472  }
473  else if(FTP_REPLY_CODE_3YZ(context->replyCode))
474  {
475  //Format ACCT command
476  error = ftpClientFormatCommand(context, "ACCT", account);
477 
478  //Check status code
479  if(!error)
480  {
481  //Send ACCT command and wait for the server's response
483  }
484  }
485  else
486  {
487  //Update FTP client state
489  //Report an error
491  }
492  }
493  }
494  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_3)
495  {
496  //Send ACCT command and wait for the server's response
497  error = ftpClientSendCommand(context);
498 
499  //Check status code
500  if(!error)
501  {
502  //Check FTP response code
503  if(!FTP_REPLY_CODE_2YZ(context->replyCode))
504  {
505  //Report an error
507  }
508 
509  //Update FTP client state
511  //We are done
512  break;
513  }
514  }
515  else
516  {
517  //Invalid state
518  error = ERROR_WRONG_STATE;
519  }
520  }
521 
522  //Check status code
523  if(error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
524  {
525  //Check whether the timeout has elapsed
526  error = ftpClientCheckTimeout(context);
527  }
528 
529  //Return status code
530  return error;
531 }
532 
533 
534 /**
535  * @brief Get current working directory
536  * @param[in] context Pointer to the FTP client context
537  * @param[out] path Output buffer where to store the current directory
538  * @param[in] maxLen Maximum number of characters the buffer can hold
539  * @return Error code
540  **/
541 
543  size_t maxLen)
544 {
545  error_t error;
546 
547  //Check parameters
548  if(context == NULL || path == NULL)
550 
551  //Initialize status code
552  error = NO_ERROR;
553 
554  //Execute FTP command
555  while(!error)
556  {
557  //Check current state
558  if(context->state == FTP_CLIENT_STATE_CONNECTED)
559  {
560  //Format PWD command
561  error = ftpClientFormatCommand(context, "PWD", NULL);
562 
563  //Check status code
564  if(!error)
565  {
566  //Send PWD command and wait for the server's response
568  }
569  }
570  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_1)
571  {
572  //Send PWD command and wait for the server's response
573  error = ftpClientSendCommand(context);
574 
575  //Check status code
576  if(!error)
577  {
578  //Check FTP response code
579  if(FTP_REPLY_CODE_2YZ(context->replyCode))
580  {
581  //Parse server's response
582  error = ftpClientParsePwdReply(context, path, maxLen);
583  }
584  else
585  {
586  //Report an error
588  }
589 
590  //Update FTP client state
592  //We are done
593  break;
594  }
595  }
596  else
597  {
598  //Invalid state
599  error = ERROR_WRONG_STATE;
600  }
601  }
602 
603  //Check status code
604  if(error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
605  {
606  //Check whether the timeout has elapsed
607  error = ftpClientCheckTimeout(context);
608  }
609 
610  //Return status code
611  return error;
612 }
613 
614 
615 /**
616  * @brief Change working directory
617  * @param[in] context Pointer to the FTP client context
618  * @param[in] path The new current working directory
619  * @return Error code
620  **/
621 
623  const char_t *path)
624 {
625  error_t error;
626 
627  //Check parameters
628  if(context == NULL || path == NULL)
630 
631  //Initialize status code
632  error = NO_ERROR;
633 
634  //Execute FTP command
635  while(!error)
636  {
637  //Check current state
638  if(context->state == FTP_CLIENT_STATE_CONNECTED)
639  {
640  //Format CWD command
641  error = ftpClientFormatCommand(context, "CWD", path);
642 
643  //Check status code
644  if(!error)
645  {
646  //Send CWD command and wait for the server's response
648  }
649  }
650  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_1)
651  {
652  //Send CWD command and wait for the server's response
653  error = ftpClientSendCommand(context);
654 
655  //Check status code
656  if(!error)
657  {
658  //Check FTP response code
659  if(!FTP_REPLY_CODE_2YZ(context->replyCode))
660  {
661  //Report an error
663  }
664 
665  //Update FTP client state
667  //We are done
668  break;
669  }
670  }
671  else
672  {
673  //Invalid state
674  error = ERROR_WRONG_STATE;
675  }
676  }
677 
678  //Check status code
679  if(error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
680  {
681  //Check whether the timeout has elapsed
682  error = ftpClientCheckTimeout(context);
683  }
684 
685  //Return status code
686  return error;
687 }
688 
689 
690 /**
691  * @brief Change to parent directory
692  * @param[in] context Pointer to the FTP client context
693  * @return Error code
694  **/
695 
697 {
698  error_t error;
699 
700  //Make sure the FTP client context is valid
701  if(context == NULL)
703 
704  //Initialize status code
705  error = NO_ERROR;
706 
707  //Execute FTP command
708  while(!error)
709  {
710  //Check current state
711  if(context->state == FTP_CLIENT_STATE_CONNECTED)
712  {
713  //Format CDUP command
714  error = ftpClientFormatCommand(context, "CDUP", NULL);
715 
716  //Check status code
717  if(!error)
718  {
719  //Send CDUP command and wait for the server's response
721  }
722  }
723  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_1)
724  {
725  //Send CDUP command and wait for the server's response
726  error = ftpClientSendCommand(context);
727 
728  //Check status code
729  if(!error)
730  {
731  //Check FTP response code
732  if(!FTP_REPLY_CODE_2YZ(context->replyCode))
733  {
734  //Report an error
736  }
737 
738  //Update FTP client state
740  //We are done
741  break;
742  }
743  }
744  else
745  {
746  //Invalid state
747  error = ERROR_WRONG_STATE;
748  }
749  }
750 
751  //Check status code
752  if(error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
753  {
754  //Check whether the timeout has elapsed
755  error = ftpClientCheckTimeout(context);
756  }
757 
758  //Return status code
759  return error;
760 }
761 
762 
763 /**
764  * @brief Open a directory
765  * @param[in] context Pointer to the FTP client context
766  * @param[in] path Path to the directory to be be opened
767  * @return Directory handle
768  **/
769 
771 {
772  error_t error;
773 
774  //Check parameters
775  if(context == NULL || path == NULL)
777 
778  //Initialize status code
779  error = NO_ERROR;
780 
781  //Execute FTP command sequence
782  while(!error)
783  {
784  //Check current state
785  if(context->state == FTP_CLIENT_STATE_CONNECTED)
786  {
787  //The data transfer is over the data connection in type ASCII or
788  //type EBCDIC (refer to RFC 959, section 4.1.3)
789  error = ftpClientFormatCommand(context, "TYPE", "A");
790 
791  //Check status code
792  if(!error)
793  {
794  //Send TYPE command and wait for the server's response
796  }
797  }
798  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_1)
799  {
800  //Send TYPE command and wait for the server's response
801  error = ftpClientSendCommand(context);
802 
803  //Check status code
804  if(!error)
805  {
806  //Check FTP response code
807  if(FTP_REPLY_CODE_2YZ(context->replyCode))
808  {
809  //Update FTP client state
811  }
812  else
813  {
814  //Report an error
816  }
817  }
818  }
819  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_2 ||
820  context->state == FTP_CLIENT_STATE_SUB_COMMAND_3 ||
821  context->state == FTP_CLIENT_STATE_SUB_COMMAND_4 ||
822  context->state == FTP_CLIENT_STATE_SUB_COMMAND_5 ||
823  context->state == FTP_CLIENT_STATE_SUB_COMMAND_6 ||
824  context->state == FTP_CLIENT_STATE_CONNECTING_TCP ||
825  context->state == FTP_CLIENT_STATE_SUB_COMMAND_8 ||
826  context->state == FTP_CLIENT_STATE_ACCEPTING_TCP ||
827  context->state == FTP_CLIENT_STATE_CONNECTING_TLS)
828  {
829  //Initiate data transfer
830  error = ftpClientInitDataTransfer(context, FALSE);
831  }
832  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_7)
833  {
834  //Format LIST command
835  if(!strcmp(path, "."))
836  ftpClientFormatCommand(context, "LIST", NULL);
837  else
838  ftpClientFormatCommand(context, "LIST", path);
839 
840  //Check status code
841  if(!error)
842  {
843  //Send LIST command and wait for the server's response
845  }
846  }
847  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_9)
848  {
849  //Flush buffer
850  context->bufferPos = 0;
851  context->commandLen = 0;
852  context->replyLen = 0;
853 
854  //The content of the directory can be transferred via the data
855  //connection
857 
858  //We are done
859  break;
860  }
861  else
862  {
863  //Invalid state
864  error = ERROR_WRONG_STATE;
865  }
866  }
867 
868  //Check status code
869  if(error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
870  {
871  //Check whether the timeout has elapsed
872  error = ftpClientCheckTimeout(context);
873  }
874 
875  //Failed to open directory?
876  if(error != NO_ERROR && error != ERROR_WOULD_BLOCK)
877  {
878  //Close data connection
879  ftpClientCloseConnection(&context->dataConnection);
880  //Update FTP client state
882  }
883 
884  //Return status code
885  return error;
886 }
887 
888 
889 /**
890  * @brief Read an entry from the directory
891  * @param[in] context Pointer to the FTP client context
892  * @param[out] dirEntry Pointer to a directory entry
893  * @return Error code
894  **/
895 
897 {
898  error_t error;
899  size_t n;
900 
901  //Check parameters
902  if(context == NULL || dirEntry == NULL)
904 
905  //Initialize status code
906  error = NO_ERROR;
907 
908  //Erase the contents of the entry
909  memset(dirEntry, 0, sizeof(FtpDirEntry));
910 
911  //Check current state
912  if(context->state == FTP_CLIENT_STATE_READING_DATA)
913  {
914  //Loop through directory entries
915  while(!error)
916  {
917  //Determine whether more data should be collected
918  if(context->replyLen < (FTP_CLIENT_BUFFER_SIZE - 1))
919  {
920  //Receive data from the FTP server
921  error = ftpClientReceiveData(&context->dataConnection,
922  context->buffer + context->replyLen,
923  FTP_CLIENT_BUFFER_SIZE - 1 - context->replyLen,
925 
926  //Check status code
927  if(error == NO_ERROR)
928  {
929  //Advance data pointer
930  context->replyLen += n;
931 
932  //Check whether the string is terminated by a CRLF sequence
933  if(context->replyLen != 0 &&
934  context->buffer[context->replyLen - 1] == '\n')
935  {
936  //Save current time
937  context->timestamp = osGetSystemTime();
938 
939  //Properly terminate the string with a NULL character
940  context->buffer[context->replyLen] = '\0';
941  //Flush buffer
942  context->replyLen = 0;
943 
944  //Remove trailing whitespace characters
945  strRemoveTrailingSpace(context->buffer);
946 
947  //Discard empty lines
948  if(context->buffer[0] != '\0')
949  {
950  //Parse current directory entry
951  error = ftpClientParseDirEntry(context->buffer, dirEntry);
952  //We are done
953  break;
954  }
955  }
956  }
957  else if(error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
958  {
959  //Check whether the timeout has elapsed
960  error = ftpClientCheckTimeout(context);
961  }
962  else
963  {
964  //Communication error
965  }
966  }
967  else
968  {
969  //Flush buffer
970  context->replyLen = 0;
971  }
972  }
973  }
974  else
975  {
976  //Invalid state
977  error = ERROR_WRONG_STATE;
978  }
979 
980  //Return status code
981  return error;
982 }
983 
984 
985 /**
986  * @brief Close directory
987  * @param[in] context Pointer to the FTP client context
988  * @return Error code
989  **/
990 
992 {
993  //Make sure the FTP client context is valid
994  if(context == NULL)
996 
997  //Close data connection and get transfer status
998  return ftpClientTerminateDataTransfer(context);
999 }
1000 
1001 
1002 /**
1003  * @brief Create a new directory
1004  * @param[in] context Pointer to the FTP client context
1005  * @param[in] path The name of the new directory
1006  * @return Error code
1007  **/
1008 
1010 {
1011  error_t error;
1012 
1013  //Check parameters
1014  if(context == NULL || path == NULL)
1015  return ERROR_INVALID_PARAMETER;
1016 
1017  //Initialize status code
1018  error = NO_ERROR;
1019 
1020  //Execute FTP command
1021  while(!error)
1022  {
1023  //Check current state
1024  if(context->state == FTP_CLIENT_STATE_CONNECTED)
1025  {
1026  //Format MKD command
1027  error = ftpClientFormatCommand(context, "MKD", path);
1028 
1029  //Check status code
1030  if(!error)
1031  {
1032  //Send MKD command and wait for the server's response
1034  }
1035  }
1036  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_1)
1037  {
1038  //Send MKD command and wait for the server's response
1039  error = ftpClientSendCommand(context);
1040 
1041  //Check status code
1042  if(!error)
1043  {
1044  //Check FTP response code
1045  if(!FTP_REPLY_CODE_2YZ(context->replyCode))
1046  {
1047  //Report an error
1048  error = ERROR_UNEXPECTED_RESPONSE;
1049  }
1050 
1051  //Update FTP client state
1053  //We are done
1054  break;
1055  }
1056  }
1057  else
1058  {
1059  //Invalid state
1060  error = ERROR_WRONG_STATE;
1061  }
1062  }
1063 
1064  //Check status code
1065  if(error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
1066  {
1067  //Check whether the timeout has elapsed
1068  error = ftpClientCheckTimeout(context);
1069  }
1070 
1071  //Return status code
1072  return error;
1073 }
1074 
1075 
1076 /**
1077  * @brief Remove a directory on the FTP server
1078  * @param[in] context Pointer to the FTP client context
1079  * @param[in] path Path to the directory to be removed
1080  * @return Error code
1081  **/
1082 
1084 {
1085  error_t error;
1086 
1087  //Check parameters
1088  if(context == NULL || path == NULL)
1089  return ERROR_INVALID_PARAMETER;
1090 
1091  //Initialize status code
1092  error = NO_ERROR;
1093 
1094  //Execute FTP command
1095  while(!error)
1096  {
1097  //Check current state
1098  if(context->state == FTP_CLIENT_STATE_CONNECTED)
1099  {
1100  //Format RMD command
1101  error = ftpClientFormatCommand(context, "RMD", path);
1102 
1103  //Check status code
1104  if(!error)
1105  {
1106  //Send RMD command and wait for the server's response
1108  }
1109  }
1110  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_1)
1111  {
1112  //Send RMD command and wait for the server's response
1113  error = ftpClientSendCommand(context);
1114 
1115  //Check status code
1116  if(!error)
1117  {
1118  //Check FTP response code
1119  if(!FTP_REPLY_CODE_2YZ(context->replyCode))
1120  {
1121  //Report an error
1122  error = ERROR_UNEXPECTED_RESPONSE;
1123  }
1124 
1125  //Update FTP client state
1127  //We are done
1128  break;
1129  }
1130  }
1131  else
1132  {
1133  //Invalid state
1134  error = ERROR_WRONG_STATE;
1135  }
1136  }
1137 
1138  //Check status code
1139  if(error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
1140  {
1141  //Check whether the timeout has elapsed
1142  error = ftpClientCheckTimeout(context);
1143  }
1144 
1145  //Return status code
1146  return error;
1147 }
1148 
1149 
1150 /**
1151  * @brief Open a file for reading, writing, or appending
1152  * @param[in] context Pointer to the FTP client context
1153  * @param[in] path Path to the file to be be opened
1154  * @param[in] mode File access mode
1155  * @return Error code
1156  **/
1157 
1159  uint_t mode)
1160 {
1161  error_t error;
1162 
1163  //Check parameters
1164  if(context == NULL || path == NULL)
1165  return ERROR_INVALID_PARAMETER;
1166 
1167  //Initialize status code
1168  error = NO_ERROR;
1169 
1170  //Execute FTP command sequence
1171  while(!error)
1172  {
1173  //Check current state
1174  if(context->state == FTP_CLIENT_STATE_CONNECTED)
1175  {
1176  //Set representation type
1177  if(mode & FTP_FILE_MODE_TEXT)
1178  {
1179  //Use ASCII type
1180  error = ftpClientFormatCommand(context, "TYPE", "A");
1181  }
1182  else
1183  {
1184  //Use image type
1185  error = ftpClientFormatCommand(context, "TYPE", "I");
1186  }
1187 
1188  //Check status code
1189  if(!error)
1190  {
1191  //Send TYPE command and wait for the server's response
1193  }
1194  }
1195  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_1)
1196  {
1197  //Send TYPE command and wait for the server's response
1198  error = ftpClientSendCommand(context);
1199 
1200  //Check status code
1201  if(!error)
1202  {
1203  //Check FTP response code
1204  if(FTP_REPLY_CODE_2YZ(context->replyCode))
1205  {
1206  //Update FTP client state
1208  }
1209  else
1210  {
1211  //Report an error
1212  error = ERROR_UNEXPECTED_RESPONSE;
1213  }
1214  }
1215  }
1216  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_2 ||
1217  context->state == FTP_CLIENT_STATE_SUB_COMMAND_3 ||
1218  context->state == FTP_CLIENT_STATE_SUB_COMMAND_4 ||
1219  context->state == FTP_CLIENT_STATE_SUB_COMMAND_5 ||
1220  context->state == FTP_CLIENT_STATE_SUB_COMMAND_6 ||
1221  context->state == FTP_CLIENT_STATE_CONNECTING_TCP ||
1222  context->state == FTP_CLIENT_STATE_SUB_COMMAND_8 ||
1223  context->state == FTP_CLIENT_STATE_ACCEPTING_TCP ||
1224  context->state == FTP_CLIENT_STATE_CONNECTING_TLS)
1225  {
1226  //Initiate data transfer
1228  error = ftpClientInitDataTransfer(context, TRUE);
1229  else
1230  error = ftpClientInitDataTransfer(context, FALSE);
1231  }
1232  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_7)
1233  {
1234  //Format STOR/APPE/RETR command
1236  ftpClientFormatCommand(context, "STOR", path);
1237  else if(mode & FTP_FILE_MODE_APPEND)
1238  ftpClientFormatCommand(context, "APPE", path);
1239  else
1240  ftpClientFormatCommand(context, "RETR", path);
1241 
1242  //Check status code
1243  if(!error)
1244  {
1245  //Send STOR/APPE/RETR command and wait for the server's response
1247  }
1248  }
1249  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_9)
1250  {
1251  //Check data transfer direction
1253  {
1254  //The content of the file can be written via the data connection
1256  }
1257  else
1258  {
1259  //The content of the file can be read via the data connection
1261  }
1262 
1263  //We are done
1264  break;
1265  }
1266  else
1267  {
1268  //Invalid state
1269  error = ERROR_WRONG_STATE;
1270  }
1271  }
1272 
1273  //Check status code
1274  if(error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
1275  {
1276  //Check whether the timeout has elapsed
1277  error = ftpClientCheckTimeout(context);
1278  }
1279 
1280  //Failed to open file?
1281  if(error != NO_ERROR && error != ERROR_WOULD_BLOCK)
1282  {
1283  //Close data connection
1284  ftpClientCloseConnection(&context->dataConnection);
1285  //Update FTP client state
1287  }
1288 
1289  //Return status code
1290  return error;
1291 }
1292 
1293 
1294 /**
1295  * @brief Write to a remote file
1296  * @param[in] context Pointer to the FTP client context
1297  * @param[in] data Pointer to a buffer containing the data to be written
1298  * @param[in] length Number of data bytes to write
1299  * @param[in] written Number of bytes that have been written
1300  * @param[in] flags Set of flags that influences the behavior of this function
1301  * @return Error code
1302  **/
1303 
1305  size_t length, size_t *written, uint_t flags)
1306 {
1307  error_t error;
1308 
1309  //Make sure the FTP client context is valid
1310  if(context == NULL)
1311  return ERROR_INVALID_PARAMETER;
1312 
1313  //Check current state
1314  if(context->state == FTP_CLIENT_STATE_WRITING_DATA)
1315  {
1316  //Transmit data to the FTP server
1317  error = ftpClientSendData(&context->dataConnection, data, length,
1318  NULL, flags);
1319 
1320  //Check status code
1321  if(error == NO_ERROR)
1322  {
1323  //Save current time
1324  context->timestamp = osGetSystemTime();
1325  }
1326  else if(error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
1327  {
1328  //Check whether the timeout has elapsed
1329  error = ftpClientCheckTimeout(context);
1330  }
1331  else
1332  {
1333  //Communication error
1334  }
1335  }
1336  else
1337  {
1338  //Invalid state
1339  error = ERROR_WRONG_STATE;
1340  }
1341 
1342  //Return status code
1343  return error;
1344 }
1345 
1346 
1347 /**
1348  * @brief Read from a remote file
1349  * @param[in] context Pointer to the FTP client context
1350  * @param[out] data Buffer where to store the incoming data
1351  * @param[in] size Maximum number of bytes that can be read
1352  * @param[out] length Actual number of bytes that have been read
1353  * @param[in] flags Set of flags that influences the behavior of this function
1354  * @return Error code
1355  **/
1356 
1357 error_t ftpClientReadFile(FtpClientContext *context, void *data, size_t size,
1358  size_t *length, uint_t flags)
1359 {
1360  error_t error;
1361 
1362  //Make sure the FTP client context is valid
1363  if(context == NULL)
1364  return ERROR_INVALID_PARAMETER;
1365 
1366  //Check current state
1367  if(context->state == FTP_CLIENT_STATE_READING_DATA)
1368  {
1369  //Receive data from the FTP server
1370  error = ftpClientReceiveData(&context->dataConnection, data, size,
1371  length, flags);
1372 
1373  //Check status code
1374  if(error == NO_ERROR)
1375  {
1376  //Save current time
1377  context->timestamp = osGetSystemTime();
1378  }
1379  else if(error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
1380  {
1381  //Check whether the timeout has elapsed
1382  error = ftpClientCheckTimeout(context);
1383  }
1384  else
1385  {
1386  //Communication error
1387  }
1388  }
1389  else
1390  {
1391  //Invalid state
1392  error = ERROR_WRONG_STATE;
1393  }
1394 
1395  //Return status code
1396  return error;
1397 }
1398 
1399 
1400 /**
1401  * @brief Close file
1402  * @param[in] context Pointer to the FTP client context
1403  * @return Error code
1404  **/
1405 
1407 {
1408  //Make sure the FTP client context is valid
1409  if(context == NULL)
1410  return ERROR_INVALID_PARAMETER;
1411 
1412  //Close data connection and get transfer status
1413  return ftpClientTerminateDataTransfer(context);
1414 }
1415 
1416 
1417 /**
1418  * @brief Rename a remote file
1419  * @param[in] context Pointer to the FTP client context
1420  * @param[in] oldName The name of the remote file to rename
1421  * @param[in] newName The new name of the remote file
1422  * @return Error code
1423  **/
1424 
1426  const char_t *newName)
1427 {
1428  error_t error;
1429 
1430  //Check parameters
1431  if(context == NULL || oldName == NULL || newName == NULL)
1432  return ERROR_INVALID_PARAMETER;
1433 
1434  //Initialize status code
1435  error = NO_ERROR;
1436 
1437  //Execute FTP command sequence
1438  while(!error)
1439  {
1440  //Check current state
1441  if(context->state == FTP_CLIENT_STATE_CONNECTED)
1442  {
1443  //Format RNFR command
1444  error = ftpClientFormatCommand(context, "RNFR", oldName);
1445 
1446  //Check status code
1447  if(!error)
1448  {
1449  //Send USER command and wait for the server's response
1451  }
1452  }
1453  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_1)
1454  {
1455  //Send RNFR command and wait for the server's response
1456  error = ftpClientSendCommand(context);
1457 
1458  //Check status code
1459  if(!error)
1460  {
1461  //Check FTP response code
1462  if(FTP_REPLY_CODE_3YZ(context->replyCode))
1463  {
1464  //Format RNTO command
1465  error = ftpClientFormatCommand(context, "RNTO", newName);
1466 
1467  //Check status code
1468  if(!error)
1469  {
1470  //Send RNTO command and wait for the server's response
1472  }
1473  }
1474  else
1475  {
1476  //Update FTP client state
1478  //Report an error
1479  error = ERROR_UNEXPECTED_RESPONSE;
1480  }
1481  }
1482  }
1483  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_2)
1484  {
1485  //Send RNTO command and wait for the server's response
1486  error = ftpClientSendCommand(context);
1487 
1488  //Check status code
1489  if(!error)
1490  {
1491  //Check FTP response code
1492  if(!FTP_REPLY_CODE_2YZ(context->replyCode))
1493  {
1494  //Report an error
1495  error = ERROR_UNEXPECTED_RESPONSE;
1496  }
1497 
1498  //Update FTP client state
1500  //We are done
1501  break;
1502  }
1503  }
1504  else
1505  {
1506  //Invalid state
1507  error = ERROR_WRONG_STATE;
1508  }
1509  }
1510 
1511  //Check status code
1512  if(error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
1513  {
1514  //Check whether the timeout has elapsed
1515  error = ftpClientCheckTimeout(context);
1516  }
1517 
1518  //Return status code
1519  return error;
1520 }
1521 
1522 
1523 /**
1524  * @brief Delete a file
1525  * @param[in] context Pointer to the FTP client context
1526  * @param[in] path Path to the file to be be deleted
1527  * @return Error code
1528  **/
1529 
1531 {
1532  error_t error;
1533 
1534  //Check parameters
1535  if(context == NULL || path == NULL)
1536  return ERROR_INVALID_PARAMETER;
1537 
1538  //Initialize status code
1539  error = NO_ERROR;
1540 
1541  //Execute FTP command
1542  while(!error)
1543  {
1544  //Check current state
1545  if(context->state == FTP_CLIENT_STATE_CONNECTED)
1546  {
1547  //Format DELE command
1548  error = ftpClientFormatCommand(context, "DELE", path);
1549 
1550  //Check status code
1551  if(!error)
1552  {
1553  //Send DELE command and wait for the server's response
1555  }
1556  }
1557  else if(context->state == FTP_CLIENT_STATE_SUB_COMMAND_1)
1558  {
1559  //Send DELE command and wait for the server's response
1560  error = ftpClientSendCommand(context);
1561 
1562  //Check status code
1563  if(!error)
1564  {
1565  //Check FTP response code
1566  if(!FTP_REPLY_CODE_2YZ(context->replyCode))
1567  {
1568  //Report an error
1569  error = ERROR_UNEXPECTED_RESPONSE;
1570  }
1571 
1572  //Update FTP client state
1574  //We are done
1575  break;
1576  }
1577  }
1578  else
1579  {
1580  //Invalid state
1581  error = ERROR_WRONG_STATE;
1582  }
1583  }
1584 
1585  //Check status code
1586  if(error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
1587  {
1588  //Check whether the timeout has elapsed
1589  error = ftpClientCheckTimeout(context);
1590  }
1591 
1592  //Return status code
1593  return error;
1594 }
1595 
1596 
1597 /**
1598  * @brief Retrieve server's reply code
1599  * @param[in] context Pointer to the FTP client context
1600  * @return FTP reply code
1601  **/
1602 
1604 {
1605  uint_t replyCode;
1606 
1607  //Make sure the FTP client context is valid
1608  if(context != NULL)
1609  {
1610  //Get server's reply code
1611  replyCode = context->replyCode;
1612  }
1613  else
1614  {
1615  //The FTP client context is not valid
1616  replyCode = 0;
1617  }
1618 
1619  //Return FTP reply code
1620  return replyCode;
1621 }
1622 
1623 
1624 /**
1625  * @brief Gracefully disconnect from the FTP server
1626  * @param[in] context Pointer to the FTP client context
1627  * @return Error code
1628  **/
1629 
1631 {
1632  error_t error;
1633 
1634  //Make sure the FTP client context is valid
1635  if(context == NULL)
1636  return ERROR_INVALID_PARAMETER;
1637 
1638  //Initialize status code
1639  error = NO_ERROR;
1640 
1641  //Execute FTP command sequence
1642  while(!error)
1643  {
1644  //Check current state
1645  if(context->state == FTP_CLIENT_STATE_CONNECTED)
1646  {
1647  //Update FTP client state
1649  }
1650  else if(context->state == FTP_CLIENT_STATE_DISCONNECTING_1)
1651  {
1652  //Shutdown data connection
1653  error = ftpClientShutdownConnection(&context->dataConnection);
1654 
1655  //Check status code
1656  if(!error)
1657  {
1658  //Close data connection
1659  ftpClientCloseConnection(&context->dataConnection);
1660  //Update FTP client state
1662  }
1663  }
1664  else if(context->state == FTP_CLIENT_STATE_DISCONNECTING_2)
1665  {
1666  //Shutdown control connection
1667  error = ftpClientShutdownConnection(&context->controlConnection);
1668 
1669  //Check status code
1670  if(!error)
1671  {
1672  //Close control connection
1673  ftpClientCloseConnection(&context->controlConnection);
1674  //Update FTP client state
1676  }
1677  }
1678  else if(context->state == FTP_CLIENT_STATE_DISCONNECTED)
1679  {
1680  //We are done
1681  break;
1682  }
1683  else
1684  {
1685  //Invalid state
1686  error = ERROR_WRONG_STATE;
1687  }
1688  }
1689 
1690  //Check status code
1691  if(error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
1692  {
1693  //Check whether the timeout has elapsed
1694  error = ftpClientCheckTimeout(context);
1695  }
1696 
1697  //Failed to gracefully disconnect from the FTP server?
1698  if(error != NO_ERROR && error != ERROR_WOULD_BLOCK)
1699  {
1700  //Close data and control connections
1701  ftpClientCloseConnection(&context->dataConnection);
1702  ftpClientCloseConnection(&context->controlConnection);
1703 
1704  //Update FTP client state
1706  }
1707 
1708  //Return status code
1709  return error;
1710 }
1711 
1712 
1713 /**
1714  * @brief Close the connection with the FTP server
1715  * @param[in] context Pointer to the FTP client context
1716  * @return Error code
1717  **/
1718 
1720 {
1721  //Make sure the FTP client context is valid
1722  if(context == NULL)
1723  return ERROR_INVALID_PARAMETER;
1724 
1725  //Close data and control connections
1726  ftpClientCloseConnection(&context->dataConnection);
1727  ftpClientCloseConnection(&context->controlConnection);
1728 
1729  //Update FTP client state
1731 
1732  //Successful processing
1733  return NO_ERROR;
1734 }
1735 
1736 
1737 /**
1738  * @brief Release FTP client context
1739  * @param[in] context Pointer to the FTP client context
1740  **/
1741 
1743 {
1744  //Make sure the FTP client context is valid
1745  if(context != NULL)
1746  {
1747  //Close data and control connections
1748  ftpClientCloseConnection(&context->dataConnection);
1749  ftpClientCloseConnection(&context->controlConnection);
1750 
1751 #if (FTP_CLIENT_TLS_SUPPORT == ENABLED)
1752  //Release TLS session state
1753  tlsFreeSessionState(&context->tlsSession);
1754 #endif
1755 
1756  //Clear FTP client context
1757  memset(context, 0, sizeof(FtpClientContext));
1758  }
1759 }
1760 
1761 
1762 //Deprecated function
1764  const IpAddr *serverIpAddr, uint16_t serverPort, uint_t flags)
1765 {
1766  error_t error;
1767 
1768 #if (FTP_CLIENT_TLS_SUPPORT == ENABLED)
1769  FtpClientTlsInitCallback tlsInitCallback;
1770 
1771  //Initialize FTP client context
1772  tlsInitCallback = context->tlsInitCallback;
1773  error = ftpClientInit(context);
1774  context->tlsInitCallback = tlsInitCallback;
1775 #else
1776  //Initialize FTP client context
1777  error = ftpClientInit(context);
1778 #endif
1779 
1780  //Check status code
1781  if(!error)
1782  {
1783  //Bind the FTP client to a particular network interface
1784  ftpClientBindToInterface(context, interface);
1785 
1786  //Establish a connection with the specified FTP server
1787  error = ftpClientConnect(context, serverIpAddr, serverPort, flags);
1788 
1789  //Failed to establish connection?
1790  if(error)
1791  {
1792  //Clean up side effects
1793  ftpClientDeinit(context);
1794  }
1795  }
1796 
1797  //Return status code
1798  return error;
1799 }
1800 
1801 #endif
error_t ftpClientRenameFile(FtpClientContext *context, const char_t *oldName, const char_t *newName)
Rename a remote file.
Definition: ftp_client.c:1425
uint32_t systime_t
Definition: compiler_port.h:44
error_t ftpClientSetTimeout(FtpClientContext *context, systime_t timeout)
Set communication timeout.
Definition: ftp_client.c:125
char char_t
Definition: compiler_port.h:41
error_t ftpClientSendCommand(FtpClientContext *context)
Send FTP command and wait for a reply.
uint8_t flags
Definition: tcp.h:312
#define FTP_CLIENT_DEFAULT_TIMEOUT
Definition: ftp_client.h:52
error_t ftpClientClose(FtpClientContext *context)
Close the connection with the FTP server.
Definition: ftp_client.c:1719
systime_t osGetSystemTime(void)
Retrieve system time.
Debugging facilities.
#define FTP_REPLY_CODE_2YZ(code)
Definition: ftp_client.h:114
error_t ftpClientCloseDir(FtpClientContext *context)
Close directory.
Definition: ftp_client.c:991
void ftpClientCloseConnection(FtpClientSocket *connection)
Close network connection.
Invalid parameter.
Definition: error.h:45
#define FtpClientContext
Definition: ftp_client.h:121
error_t ftpClientOpenDir(FtpClientContext *context, const char_t *path)
Open a directory.
Definition: ftp_client.c:770
error_t ftpClientOpenFile(FtpClientContext *context, const char_t *path, uint_t mode)
Open a file for reading, writing, or appending.
Definition: ftp_client.c:1158
IP network address.
Definition: ip.h:57
error_t ftpClientTerminateDataTransfer(FtpClientContext *context)
Terminate data transfer.
error_t ftpClientWriteFile(FtpClientContext *context, const void *data, size_t length, size_t *written, uint_t flags)
Write to a remote file.
Definition: ftp_client.c:1304
error_t ftpClientRemoveDir(FtpClientContext *context, const char_t *path)
Remove a directory on the FTP server.
Definition: ftp_client.c:1083
#define FTP_CLIENT_BUFFER_SIZE
Definition: ftp_client.h:59
String manipulation helper functions.
error_t tlsInitSessionState(TlsSessionState *session)
Initialize session state.
Definition: tls.c:2312
#define FTP_CLIENT_MIN_TCP_BUFFER_SIZE
Definition: ftp_client.h:66
error_t ftpConnect(FtpClientContext *context, NetInterface *interface, const IpAddr *serverIpAddr, uint16_t serverPort, uint_t flags)
Definition: ftp_client.c:1763
error_t ftpClientLoginEx(FtpClientContext *context, const char_t *username, const char_t *password, const char_t *account)
Login to the FTP server using user name, password and account.
Definition: ftp_client.c:392
error_t ftpClientShutdownConnection(FtpClientSocket *connection)
Shutdown network connection.
error_t(* FtpClientTlsInitCallback)(FtpClientContext *context, TlsContext *tlsContext)
TLS initialization callback function.
Definition: ftp_client.h:216
error_t ftpClientParsePwdReply(FtpClientContext *context, char_t *path, size_t maxLen)
Parse PWD response.
error_t ftpClientOpenConnection(FtpClientContext *context, FtpClientSocket *connection, size_t txBufferSize, size_t rxBufferSize)
Open network connection.
error_t ftpClientInitDataTransfer(FtpClientContext *context, bool_t direction)
Initiate data transfer.
void ftpClientDeinit(FtpClientContext *context)
Release FTP client context.
Definition: ftp_client.c:1742
#define TRUE
Definition: os_port.h:48
error_t ftpClientChangeWorkingDir(FtpClientContext *context, const char_t *path)
Change working directory.
Definition: ftp_client.c:622
error_t ftpClientReadFile(FtpClientContext *context, void *data, size_t size, size_t *length, uint_t flags)
Read from a remote file.
Definition: ftp_client.c:1357
Error codes description.
error_t ftpClientRegisterTlsInitCallback(FtpClientContext *context, FtpClientTlsInitCallback callback)
Register TLS initialization callback function.
Definition: ftp_client.c:101
Transport protocol abstraction layer.
error_t ftpClientDisconnect(FtpClientContext *context)
Gracefully disconnect from the FTP server.
Definition: ftp_client.c:1630
FTP client (File Transfer Protocol)
error_t ftpClientInit(FtpClientContext *context)
Initialize FTP client context.
Definition: ftp_client.c:60
void ftpClientChangeState(FtpClientContext *context, FtpClientState newState)
Update FTP client state.
Helper functions for FTP client.
error_t ftpClientReadDir(FtpClientContext *context, FtpDirEntry *dirEntry)
Read an entry from the directory.
Definition: ftp_client.c:896
#define FTP_REPLY_CODE_3YZ(code)
Definition: ftp_client.h:115
void tlsFreeSessionState(TlsSessionState *session)
Properly dispose a session state.
Definition: tls.c:2594
error_t ftpClientFormatCommand(FtpClientContext *context, const char_t *command, const char_t *argument)
Format FTP command.
error_t ftpClientCheckTimeout(FtpClientContext *context)
Determine whether a timeout error has occurred.
error_t ftpClientReceiveData(FtpClientSocket *connection, void *data, size_t size, size_t *received, uint_t flags)
Receive data using the relevant transport protocol.
#define FTP_CLIENT_MIN_TLS_RX_BUFFER_SIZE
Definition: ftp_client.h:87
error_t ftpClientLogin(FtpClientContext *context, const char_t *username, const char_t *password)
Login to the FTP server using the provided user name and password.
Definition: ftp_client.c:375
Success.
Definition: error.h:42
error_t ftpClientConnect(FtpClientContext *context, const IpAddr *serverIpAddr, uint16_t serverPort, uint_t mode)
Establish a connection with the specified FTP server.
Definition: ftp_client.c:170
error_t socketConnect(Socket *socket, const IpAddr *remoteIpAddr, uint16_t remotePort)
Establish a connection to a specified socket.
Definition: socket.c:357
error_t
Error codes.
Definition: error.h:40
error_t ftpClientDeleteFile(FtpClientContext *context, const char_t *path)
Delete a file.
Definition: ftp_client.c:1530
unsigned int uint_t
Definition: compiler_port.h:43
Directory entry.
Definition: ftp_client.h:266
uint8_t data[]
Definition: dtls_misc.h:167
#define NetInterface
Definition: net.h:34
error_t ftpClientSendData(FtpClientSocket *connection, const void *data, size_t length, size_t *written, uint_t flags)
Send data using the relevant transport protocol.
error_t ftpClientParseDirEntry(char_t *line, FtpDirEntry *dirEntry)
Parse directory entry.
uint8_t mode
Definition: sntp_client.h:143
uint_t ftpClientGetReplyCode(FtpClientContext *context)
Retrieve server&#39;s reply code.
Definition: ftp_client.c:1603
#define FTP_CLIENT_TLS_TX_BUFFER_SIZE
Definition: ftp_client.h:80
error_t ftpClientOpenSecureConnection(FtpClientContext *context, FtpClientSocket *connection, size_t txBufferSize, size_t rxBufferSize)
Open secure connection.
error_t ftpClientBindToInterface(FtpClientContext *context, NetInterface *interface)
Bind the FTP client to a particular network interface.
Definition: ftp_client.c:146
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
error_t ftpClientChangeToParentDir(FtpClientContext *context)
Change to parent directory.
Definition: ftp_client.c:696
error_t ftpClientMakeDir(FtpClientContext *context, const char_t *path)
Create a new directory.
Definition: ftp_client.c:1009
#define FALSE
Definition: os_port.h:44
error_t ftpClientCloseFile(FtpClientContext *context)
Close file.
Definition: ftp_client.c:1406
error_t ftpClientGetWorkingDir(FtpClientContext *context, char_t *path, size_t maxLen)
Get current working directory.
Definition: ftp_client.c:542
void strRemoveTrailingSpace(char_t *s)
Removes all trailing whitespace from a string.
Definition: str.c:107
error_t ftpClientEstablishSecureConnection(FtpClientSocket *connection)
Establish secure connection.