FTP client library for mbed-os
Embed:
(wiki syntax)
Show/hide line numbers
FTPClient.cpp
00001 /* FTP client library 00002 * Copyright (c) 2018 Renesas Electronics Corporation 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "mbed.h" 00018 #include "FTPClient.h" 00019 00020 #define FTP_BUF_SIZE (1460) 00021 00022 //#define ftp_debug_print printf 00023 00024 #ifndef ftp_debug_print 00025 static int ftp_debug_print(const char *format, ...) { 00026 return 0; 00027 } 00028 #endif 00029 00030 FTPClient::FTPClient(NetworkInterface *net, const char* root) { 00031 _ctr_open = false; 00032 _login = false; 00033 strcpy(_root, root); 00034 p_network = net; 00035 p_ftp_buf = new char[FTP_BUF_SIZE]; 00036 } 00037 00038 FTPClient::~FTPClient() { 00039 delete [] p_ftp_buf; 00040 } 00041 00042 bool FTPClient::open(const char* ip_addr, int port, const char* user, const char* pass) { 00043 if (_ctr_open) { 00044 FTPClientControlSock.close(); 00045 } 00046 00047 FTPClientControlSock.open(p_network); 00048 if (FTPClientControlSock.connect(ip_addr, port) < 0) { 00049 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00050 return false; 00051 } 00052 _ctr_open = true; 00053 00054 if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { 00055 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00056 return false; 00057 } 00058 if (strncmp(p_ftp_buf, "220", 3) != 0) { 00059 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00060 return false; 00061 } 00062 00063 _login = false; 00064 sprintf(p_ftp_buf, "user %s\r\n", user); 00065 FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); 00066 if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { 00067 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00068 return false; 00069 } 00070 if (strncmp(p_ftp_buf, "331", 3) != 0) { 00071 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00072 return false; 00073 } 00074 00075 sprintf(p_ftp_buf, "pass %s\r\n", pass); 00076 FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); 00077 if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { 00078 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00079 return false; 00080 } 00081 if (strncmp(p_ftp_buf, "230", 3) != 0) { 00082 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00083 return false; 00084 } 00085 00086 sprintf(p_ftp_buf, "type I\r\n"); 00087 FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); 00088 if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { 00089 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00090 return false; 00091 } 00092 00093 _login = true; 00094 return true; 00095 } 00096 00097 bool FTPClient::quit() { 00098 if (!_login) { 00099 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00100 return false; 00101 } 00102 00103 sprintf(p_ftp_buf, "quit\r\n"); 00104 FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); 00105 if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { 00106 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00107 return false; 00108 } 00109 if (strncmp(p_ftp_buf, "250", 3) != 0) { 00110 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00111 return false; 00112 } 00113 _login = false; 00114 00115 FTPClientControlSock.close(); 00116 _ctr_open = false; 00117 return true; 00118 } 00119 00120 bool FTPClient::get(const char* file_name) { 00121 FILE* fp; 00122 int size; 00123 00124 if (!_login) { 00125 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00126 return false; 00127 } 00128 00129 if (!open_data_sock()) { 00130 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00131 return false; 00132 } 00133 00134 FTPClientDataSock.set_timeout(500); 00135 sprintf(p_ftp_buf, "retr %s\r\n", file_name); 00136 FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); 00137 if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { 00138 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00139 return false; 00140 } 00141 if ((strncmp(p_ftp_buf, "150", 3) != 0) && (strncmp(p_ftp_buf, "125", 3) != 0)) { 00142 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00143 return false; 00144 } 00145 00146 sprintf(p_ftp_buf, "%s/%s", _root, file_name); 00147 fp = fopen(p_ftp_buf, "w"); 00148 while (1) { 00149 size = FTPClientDataSock.recv(p_ftp_buf, FTP_BUF_SIZE); 00150 if (size > 0) { 00151 fwrite(p_ftp_buf, size, sizeof(char), fp); 00152 } else { 00153 break; 00154 } 00155 } 00156 fclose(fp); 00157 FTPClientDataSock.close(); 00158 00159 if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { 00160 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00161 return false; 00162 } 00163 if (strncmp(p_ftp_buf, "226", 3) != 0) { 00164 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00165 return false; 00166 } 00167 return true; 00168 } 00169 00170 bool FTPClient::put(const char* file_name) { 00171 FILE* fp; 00172 int32_t remain_size; 00173 int32_t send_size; 00174 00175 if (!_login) { 00176 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00177 return false; 00178 } 00179 00180 if (!open_data_sock()) { 00181 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00182 return false; 00183 } 00184 00185 FTPClientDataSock.set_timeout(osWaitForever); 00186 sprintf(p_ftp_buf, "stor %s\r\n", file_name); 00187 FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); 00188 if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { 00189 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00190 return false; 00191 } 00192 if ((strncmp(p_ftp_buf, "150", 3) != 0) && (strncmp(p_ftp_buf, "125", 3) != 0)) { 00193 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00194 return false; 00195 } 00196 00197 sprintf(p_ftp_buf, "%s/%s", _root, file_name); 00198 fp = fopen(p_ftp_buf, "r"); 00199 fseek(fp, 0, SEEK_END); 00200 remain_size = ftell(fp); 00201 fseek(fp, 0, SEEK_SET); 00202 00203 while (remain_size > 0) { 00204 if (remain_size > FTP_BUF_SIZE) { 00205 send_size = FTP_BUF_SIZE; 00206 } else { 00207 send_size = remain_size; 00208 } 00209 fread(p_ftp_buf, 1, send_size, fp); 00210 FTPClientDataSock.send(p_ftp_buf, send_size); 00211 remain_size -= send_size; 00212 } 00213 fclose(fp); 00214 FTPClientDataSock.close(); 00215 00216 if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { 00217 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00218 return false; 00219 } 00220 if (strncmp(p_ftp_buf, "226", 3) != 0) { 00221 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00222 return false; 00223 } 00224 return true; 00225 } 00226 00227 bool FTPClient::del(const char* file_name) { 00228 if (!_login) { 00229 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00230 return false; 00231 } 00232 00233 sprintf(p_ftp_buf, "dele %s\r\n", file_name); 00234 FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); 00235 if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { 00236 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00237 return false; 00238 } 00239 if (strncmp(p_ftp_buf, "250", 3) != 0) { 00240 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00241 return false; 00242 } 00243 00244 return true; 00245 } 00246 00247 bool FTPClient::mkdir(const char* dir_name) { 00248 if (!_login) { 00249 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00250 return false; 00251 } 00252 00253 sprintf(p_ftp_buf, "xmkd %s\r\n", dir_name); 00254 FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); 00255 if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { 00256 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00257 return false; 00258 } 00259 if (strncmp(p_ftp_buf, "257", 3) != 0) { 00260 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00261 return false; 00262 } 00263 00264 return true; 00265 } 00266 00267 bool FTPClient::cd(const char* dir_name) { 00268 if (!_login) { 00269 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00270 return false; 00271 } 00272 00273 sprintf(p_ftp_buf, "cwd %s\r\n", dir_name); 00274 FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); 00275 if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { 00276 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00277 return false; 00278 } 00279 if (strncmp(p_ftp_buf, "250", 3) != 0) { 00280 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00281 return false; 00282 } 00283 00284 return true; 00285 } 00286 00287 bool FTPClient::dir(char* list_buf, int buf_size) { 00288 int size; 00289 int idx = 0; 00290 int remain_size = buf_size - 1; 00291 00292 if (list_buf == NULL) { 00293 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00294 return false; 00295 } 00296 list_buf[0] = '\0'; 00297 00298 if (!_login) { 00299 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00300 return false; 00301 } 00302 00303 if (!open_data_sock()) { 00304 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00305 return false; 00306 } 00307 00308 FTPClientDataSock.set_timeout(500); 00309 sprintf(p_ftp_buf, "list\r\n"); 00310 FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); 00311 if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { 00312 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00313 return false; 00314 } 00315 if ((strncmp(p_ftp_buf, "150", 3) != 0) && (strncmp(p_ftp_buf, "125", 3) != 0)) { 00316 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00317 return false; 00318 } 00319 00320 while (remain_size > 0) { 00321 size = FTPClientDataSock.recv(p_ftp_buf, FTP_BUF_SIZE); 00322 if (size > 0) { 00323 if (size > remain_size) { 00324 size = remain_size; 00325 } 00326 memcpy(&list_buf[idx], p_ftp_buf, size); 00327 idx += size; 00328 remain_size -= size; 00329 } else { 00330 break; 00331 } 00332 } 00333 list_buf[idx] = '\0'; 00334 FTPClientDataSock.close(); 00335 00336 if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { 00337 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00338 return false; 00339 } 00340 if (strncmp(p_ftp_buf, "226", 3) != 0) { 00341 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00342 return false; 00343 } 00344 return true; 00345 } 00346 00347 bool FTPClient::ls(char* list_buf, int buf_size) { 00348 int size; 00349 int idx = 0; 00350 int remain_size = buf_size - 1; 00351 00352 if (list_buf == NULL) { 00353 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00354 return false; 00355 } 00356 list_buf[0] = '\0'; 00357 00358 if (!_login) { 00359 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00360 return false; 00361 } 00362 00363 if (!open_data_sock()) { 00364 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00365 return false; 00366 } 00367 00368 FTPClientDataSock.set_timeout(500); 00369 sprintf(p_ftp_buf, "nlst\r\n"); 00370 FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); 00371 if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { 00372 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00373 return false; 00374 } 00375 if ((strncmp(p_ftp_buf, "150", 3) != 0) && (strncmp(p_ftp_buf, "125", 3) != 0)) { 00376 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00377 return false; 00378 } 00379 00380 while (remain_size > 0) { 00381 size = FTPClientDataSock.recv(p_ftp_buf, FTP_BUF_SIZE); 00382 if (size > 0) { 00383 if (size > remain_size) { 00384 size = remain_size; 00385 } 00386 memcpy(&list_buf[idx], p_ftp_buf, size); 00387 idx += size; 00388 remain_size -= size; 00389 } else { 00390 break; 00391 } 00392 } 00393 list_buf[idx] = '\0'; 00394 FTPClientDataSock.close(); 00395 00396 if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { 00397 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00398 return false; 00399 } 00400 if (strncmp(p_ftp_buf, "226", 3) != 0) { 00401 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00402 return false; 00403 } 00404 return true; 00405 } 00406 00407 bool FTPClient::open_data_sock() { 00408 uint8_t ip_addr[4]; 00409 int i; 00410 int remote_port = 0; 00411 char* token = NULL; 00412 char* savept = NULL; 00413 00414 sprintf(p_ftp_buf, "pasv\r\n"); 00415 FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); 00416 if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { 00417 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00418 return false; 00419 } 00420 if (strncmp(p_ftp_buf, "227", 3) != 0) { 00421 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00422 return false; 00423 } 00424 00425 token = strchr(p_ftp_buf, '(') + 1; 00426 for (i = 0; i < 4; i++) { 00427 token = strtok_r(token, ",", &savept); 00428 ip_addr[i] = (uint8_t)atoi(token); 00429 token = savept; 00430 if (token == NULL) { 00431 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00432 return false; 00433 } 00434 } 00435 00436 for (i = 0; i < 2; i++) { 00437 token = strtok_r(token, ",)", &savept); 00438 remote_port <<= 8; 00439 remote_port += atoi(token); 00440 token = savept; 00441 if (token == NULL) { 00442 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00443 return false; 00444 } 00445 } 00446 sprintf(ftp_data_ip_addr, "%d.%d.%d.%d", ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]); 00447 00448 FTPClientDataSock.open(p_network); 00449 for (i = 0; i < 20; i++) { 00450 if (FTPClientDataSock.connect(ftp_data_ip_addr, remote_port) >= 0) { 00451 return true; 00452 } 00453 wait(1); 00454 } 00455 ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); 00456 return false; 00457 } 00458
Generated on Thu Jul 14 2022 08:33:19 by
![doxygen](doxygen.png)