FTP client library for mbed-os
FTPClient.cpp
- Committer:
- dkato
- Date:
- 2020-02-28
- Revision:
- 2:88b7399c8260
- Parent:
- 1:e069c405c934
File content as of revision 2:88b7399c8260:
/* FTP client library * Copyright (c) 2018 Renesas Electronics Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "mbed.h" #include "FTPClient.h" #define FTP_BUF_SIZE (1460) //#define ftp_debug_print printf #ifndef ftp_debug_print static int ftp_debug_print(const char *format, ...) { return 0; } #endif FTPClient::FTPClient(NetworkInterface *net, const char* root) { _ctr_open = false; _login = false; strcpy(_root, root); p_network = net; p_ftp_buf = new char[FTP_BUF_SIZE]; } FTPClient::~FTPClient() { delete [] p_ftp_buf; } bool FTPClient::open(const char* ip_addr, int port, const char* user, const char* pass) { if (_ctr_open) { FTPClientControlSock.close(); } FTPClientControlSock.open(p_network); if (FTPClientControlSock.connect(ip_addr, port) < 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } _ctr_open = true; if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } if (strncmp(p_ftp_buf, "220", 3) != 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } _login = false; sprintf(p_ftp_buf, "user %s\r\n", user); FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } if (strncmp(p_ftp_buf, "331", 3) != 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } sprintf(p_ftp_buf, "pass %s\r\n", pass); FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } if (strncmp(p_ftp_buf, "230", 3) != 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } sprintf(p_ftp_buf, "type I\r\n"); FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } _login = true; return true; } bool FTPClient::quit() { if (!_login) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } sprintf(p_ftp_buf, "quit\r\n"); FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } if (strncmp(p_ftp_buf, "250", 3) != 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } _login = false; FTPClientControlSock.close(); _ctr_open = false; return true; } bool FTPClient::get(const char* file_name) { FILE* fp; int size; if (!_login) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } if (!open_data_sock()) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } FTPClientDataSock.set_timeout(500); sprintf(p_ftp_buf, "retr %s\r\n", file_name); FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } if ((strncmp(p_ftp_buf, "150", 3) != 0) && (strncmp(p_ftp_buf, "125", 3) != 0)) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } sprintf(p_ftp_buf, "%s/%s", _root, file_name); fp = fopen(p_ftp_buf, "w"); while (1) { size = FTPClientDataSock.recv(p_ftp_buf, FTP_BUF_SIZE); if (size > 0) { fwrite(p_ftp_buf, size, sizeof(char), fp); } else { break; } } fclose(fp); FTPClientDataSock.close(); if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } if (strncmp(p_ftp_buf, "226", 3) != 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } return true; } bool FTPClient::put(const char* file_name) { FILE* fp; int32_t remain_size; int32_t send_size; if (!_login) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } if (!open_data_sock()) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } FTPClientDataSock.set_timeout(osWaitForever); sprintf(p_ftp_buf, "stor %s\r\n", file_name); FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } if ((strncmp(p_ftp_buf, "150", 3) != 0) && (strncmp(p_ftp_buf, "125", 3) != 0)) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } sprintf(p_ftp_buf, "%s/%s", _root, file_name); fp = fopen(p_ftp_buf, "r"); fseek(fp, 0, SEEK_END); remain_size = ftell(fp); fseek(fp, 0, SEEK_SET); while (remain_size > 0) { if (remain_size > FTP_BUF_SIZE) { send_size = FTP_BUF_SIZE; } else { send_size = remain_size; } fread(p_ftp_buf, 1, send_size, fp); FTPClientDataSock.send(p_ftp_buf, send_size); remain_size -= send_size; } fclose(fp); FTPClientDataSock.close(); if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } if (strncmp(p_ftp_buf, "226", 3) != 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } return true; } bool FTPClient::del(const char* file_name) { if (!_login) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } sprintf(p_ftp_buf, "dele %s\r\n", file_name); FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } if (strncmp(p_ftp_buf, "250", 3) != 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } return true; } bool FTPClient::mkdir(const char* dir_name) { if (!_login) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } sprintf(p_ftp_buf, "xmkd %s\r\n", dir_name); FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } if (strncmp(p_ftp_buf, "257", 3) != 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } return true; } bool FTPClient::cd(const char* dir_name) { if (!_login) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } sprintf(p_ftp_buf, "cwd %s\r\n", dir_name); FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } if (strncmp(p_ftp_buf, "250", 3) != 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } return true; } bool FTPClient::dir(char* list_buf, int buf_size) { int size; int idx = 0; int remain_size = buf_size - 1; if (list_buf == NULL) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } list_buf[0] = '\0'; if (!_login) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } if (!open_data_sock()) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } FTPClientDataSock.set_timeout(500); sprintf(p_ftp_buf, "list\r\n"); FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } if ((strncmp(p_ftp_buf, "150", 3) != 0) && (strncmp(p_ftp_buf, "125", 3) != 0)) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } while (remain_size > 0) { size = FTPClientDataSock.recv(p_ftp_buf, FTP_BUF_SIZE); if (size > 0) { if (size > remain_size) { size = remain_size; } memcpy(&list_buf[idx], p_ftp_buf, size); idx += size; remain_size -= size; } else { break; } } list_buf[idx] = '\0'; FTPClientDataSock.close(); if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } if (strncmp(p_ftp_buf, "226", 3) != 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } return true; } bool FTPClient::ls(char* list_buf, int buf_size) { int size; int idx = 0; int remain_size = buf_size - 1; if (list_buf == NULL) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } list_buf[0] = '\0'; if (!_login) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } if (!open_data_sock()) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } FTPClientDataSock.set_timeout(500); sprintf(p_ftp_buf, "nlst\r\n"); FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } if ((strncmp(p_ftp_buf, "150", 3) != 0) && (strncmp(p_ftp_buf, "125", 3) != 0)) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } while (remain_size > 0) { size = FTPClientDataSock.recv(p_ftp_buf, FTP_BUF_SIZE); if (size > 0) { if (size > remain_size) { size = remain_size; } memcpy(&list_buf[idx], p_ftp_buf, size); idx += size; remain_size -= size; } else { break; } } list_buf[idx] = '\0'; FTPClientDataSock.close(); if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } if (strncmp(p_ftp_buf, "226", 3) != 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } return true; } bool FTPClient::open_data_sock() { uint8_t ip_addr[4]; int i; int remote_port = 0; char* token = NULL; char* savept = NULL; sprintf(p_ftp_buf, "pasv\r\n"); FTPClientControlSock.send(p_ftp_buf, strlen(p_ftp_buf)); if (FTPClientControlSock.recv(p_ftp_buf, FTP_BUF_SIZE) <= 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } if (strncmp(p_ftp_buf, "227", 3) != 0) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } token = strchr(p_ftp_buf, '(') + 1; for (i = 0; i < 4; i++) { token = strtok_r(token, ",", &savept); ip_addr[i] = (uint8_t)atoi(token); token = savept; if (token == NULL) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } } for (i = 0; i < 2; i++) { token = strtok_r(token, ",)", &savept); remote_port <<= 8; remote_port += atoi(token); token = savept; if (token == NULL) { ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; } } sprintf(ftp_data_ip_addr, "%d.%d.%d.%d", ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]); FTPClientDataSock.open(p_network); for (i = 0; i < 20; i++) { if (FTPClientDataSock.connect(ftp_data_ip_addr, remote_port) >= 0) { return true; } wait(1); } ftp_debug_print("ERROR: %s(%d)\r\n", __FILE__, __LINE__); return false; }