diff --git a/APP_Framework/Applications/app_test/Makefile b/APP_Framework/Applications/app_test/Makefile index 6016dcb7a..9d189ae41 100644 --- a/APP_Framework/Applications/app_test/Makefile +++ b/APP_Framework/Applications/app_test/Makefile @@ -122,7 +122,7 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y) endif ifeq ($(CONFIG_USER_TEST_FTPCLIENT),y) - SRC_FILES += + SRC_FILES += test_ftpclient/test_ftpclient.c test_ftpclient/libftp/libftp.c endif ifeq ($(CONFIG_USER_TEST_LORA_P2P),y) diff --git a/APP_Framework/Applications/app_test/test_ftpclient/Makefile b/APP_Framework/Applications/app_test/test_ftpclient/Makefile new file mode 100755 index 000000000..517a2af5c --- /dev/null +++ b/APP_Framework/Applications/app_test/test_ftpclient/Makefile @@ -0,0 +1,12 @@ +ifeq ($(CONFIG_ADD_XIZI_FEATURES),y) +SRC_FILES := test_ftpclient.c ./libftp/libftp.c +include $(KERNEL_ROOT)/compiler.mk +endif + +include $(KERNEL_ROOT)/.config +ifeq ($(CONFIG_ADD_NUTTX_FEATURES),y) + include $(APPDIR)/Make.defs + CSRCS += test_ftpclient.c ./libftp/libftp.c + include $(APPDIR)/Application.mk +endif + diff --git a/APP_Framework/Applications/app_test/test_ftpclient/libftp/libftp.c b/APP_Framework/Applications/app_test/test_ftpclient/libftp/libftp.c new file mode 100644 index 000000000..dae5939b3 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_ftpclient/libftp/libftp.c @@ -0,0 +1,995 @@ +/****************************************Copyright (c)**************************************************** +** fhqlongteng@163.com +** QQ:283669063 +**--------------File Info--------------------------------------------------------------------------------- +** File name: zFTP.c +** Last modified Date: 2020-12-01 +** Last Version: V1.00 +** Descriptions: ZFTP协议实现程序 +** +**-------------------------------------------------------------------------------------------------------- +** Created by: Zhao shimin +** Created date: 2020-12-01 +** Version: V1.00 +** Descriptions: +** +** +**-------------------------------------------------------------------------------------------------------- +** Modified by: +** Modified date: +** Version: +** Descriptions: +** +** Rechecked by: +*********************************************************************************************************/ + +#include "libftp.h" + +#ifdef ADD_XIZI_FEATURES +#include +#include +#include "lwip/sys.h" +#include +#endif + +#ifdef ADD_NUTTX_FEATURES +#include +#include +#include +#include "stdio.h" +#endif + + + +/********************************************************************************************************* +** Function name: zFTP_wait_server_ack() +** Descriptions: FTP client wait server ack +** input parameters: socket, ack_code, wait_time +** output parameters: None +** Returned value: EOK, -ERROR +*********************************************************************************************************/ +static int zFTP_wait_server_ack(int socket, uint32_t *ack_code, uint32_t wait_time) +{ + fd_set readset; + struct timeval timeout; + char ftp_recv_buf[100] = {0}; + int recv_len = 0; + int code= 0; + + timeout.tv_sec = wait_time/1000; + timeout.tv_usec = 0; + + /*wait the ack*/ + + FD_ZERO(&readset); + FD_SET(socket, &readset); + + if (select(socket + 1, &readset, NULL, NULL, &timeout) <= 0) + { + printf("select the socket timeout!"); + return -ERROR; + } + + // Wait and receive the packet back from the server. If n == -1, it failed. + recv_len = recv(socket, (char*)ftp_recv_buf, sizeof(ftp_recv_buf), 0); + + if (recv_len < 0) + { + printf("reading from socket error!"); + return -ERROR; + } + + + + if(1 == sscanf(ftp_recv_buf, "%d", &code)) + { + *ack_code = code; + return EOK; + } + else + { + return -ERROR; + } + + +} + +/********************************************************************************************************* +** Function name: zFTP_send_cmd_wait_server_ack() +** Descriptions: FTP client send the command and wait the sever ack +** input parameters: socket, cmd, cmd_len, ack_code, wait_time +** output parameters: None +** Returned value: EOK, -ERROR +*********************************************************************************************************/ +static int zFTP_send_cmd_wait_server_ack(int socket, char *cmd, uint32_t cmd_len, + uint32_t *ack_code, uint32_t wait_time) +{ + fd_set readset; + struct timeval timeout; + char ftp_recv_buf[100] = {0}; + int len = 0; + int code= 0; + + if((NULL == cmd) || (NULL == ack_code)) + { + return -ERROR; + } + + timeout.tv_sec = wait_time/1000; + timeout.tv_usec = 0; + + FD_ZERO(&readset); + FD_SET(socket, &readset); + + /*发送指令*/ + len = send(socket, (char*)cmd, cmd_len, 0); + + if (len < 0) { + printf("send cmd error!"); + return -ERROR; + } + + /*等待应答*/ + if (select(socket + 1, &readset, NULL, NULL, &timeout) <= 0) { + printf("select the socket timeout!"); + return -ETIMEOUT; + } + + // Wait and receive the packet back from the server. If n == -1, it failed. + len = recv(socket, (char*)ftp_recv_buf, sizeof(ftp_recv_buf), 0); + + if (len < 0) { + printf("reading from socket error!"); + return -ERROR; + } + + if(1 == sscanf(ftp_recv_buf, "%d", &code)) + { + *ack_code = code; + return EOK; + } + else + { + printf("Rcv data:%s", ftp_recv_buf); + return -ERROR; + } + +} + +/********************************************************************************************************* +** Function name: zFTP_filesize_send_cmd() +** Descriptions: zFTP send the get filesize command +** input parameters: 无 +** output parameters: 无 +** Returned value: 无 +*********************************************************************************************************/ +static int zFTP_filesize_send_cmd(int socket, char *cmd, uint32_t cmd_len, uint32_t *ack_code, + uint32_t *file_size, uint32_t wait_time) +{ + fd_set readset; + struct timeval timeout; + char ftp_recv_buf[100] = {0}; + int len = 0; + int code= 0; + int a= 0; + + if((NULL == ack_code) || (NULL == file_size) || + (NULL == cmd)) + { + return -ERROR; + } + + timeout.tv_sec = wait_time/1000; + timeout.tv_usec = 0; + + FD_ZERO(&readset); + FD_SET(socket, &readset); + + /*发送指令*/ + len = send(socket, cmd, cmd_len, 0); + + if (len < 0) { + printf("send cmd error!"); + return -ERROR; + } + + /*等待应答*/ + if (select(socket + 1, &readset, NULL, NULL, &timeout) <= 0) { + printf("select the socket timeout!"); + return -ETIMEOUT; + } + + // Wait and receive the packet back from the server. If n == -1, it failed. + len = recv(socket, (char*)ftp_recv_buf, sizeof(ftp_recv_buf), 0); + + if (len < 0) { + printf("reading from socket error!"); + return -ERROR; + } + + /*获取文件大小和应答码*/ + if(2 == sscanf(ftp_recv_buf, "%d %d", &code, &a)) + { + *ack_code = code; + *file_size = a; + return EOK; + } + else + { + printf("Rcv data:%s", ftp_recv_buf); + return -ERROR; + } + + +} + + + +/********************************************************************************************************* +** Function name: ftp_pasv_mode() +** Descriptions: FTP客户端发送命令给服务器进入pasv模式 +** input parameters: 无 +** output parameters: 无 +** Returned value: 无 +*********************************************************************************************************/ +static int zFTP_pasv_mode(int socket,uint32_t *ack_code, uint16_t *server_port, uint32_t wait_time) +{ + fd_set readset; + struct timeval timeout; + char ftp_recv_buf[80] = {0}; + int len = 0; + int code= 0; + int a,b,c,d,e,f = 0; + + if((NULL == ack_code) || (NULL == server_port)) + { + return -ERROR; + } + + timeout.tv_sec = wait_time/1000; + timeout.tv_usec = 0; + + FD_ZERO(&readset); + FD_SET(socket, &readset); + + /*发送指令*/ + len = send(socket, "PASV\r\n", strlen("PASV\r\n"), 0); + + if (len < 0) { + printf("send cmd error!"); + return -ERROR; + } + + /*等待应答*/ + if (select(socket + 1, &readset, NULL, NULL, &timeout) <= 0) { + printf("select the socket timeout!"); + return -ETIMEOUT; + } + + // Wait and receive the packet back from the server. If n == -1, it failed. + len = recv(socket, (char*)ftp_recv_buf, sizeof(ftp_recv_buf), 0); + + if (len < 0) { + printf("reading from socket error!"); + return -ERROR; + } + + /*跳过非数字字符来取出IP和端口号*/ + if(7 == sscanf(ftp_recv_buf, "%d%*[^(](%d,%d,%d,%d,%d,%d", &code,&a,&b,&c,&d,&e,&f)) + { + *ack_code = code; + *server_port= e *256+f; + return EOK; + } + else + { + printf("Rcv data:%s", ftp_recv_buf); + return -ERROR; + } + + +} + + + +/********************************************************************************************************* +** Function name: zFTP_upload_file_data() +** Descriptions: zFTP download the file data +** input parameters: socket, buf, buf_size, wait_time +** output parameters: rd_len +** Returned value: EOK, -ERROR +*********************************************************************************************************/ +static int zFTP_upload_file_data(zftp_client *ftp, char *file_name, uint32_t wait_time) +{ + struct timeval timeout; + fd_set writeset; + int socket= -1; + uint8_t *file_buf = NULL; + uint32_t rd_len = 0, file_pos= 0, total_len = 0; + + + + timeout.tv_sec = wait_time/1000; + timeout.tv_usec = 0; + + + socket = ftp->data_socket; + + file_buf = malloc(ZFTP_FILE_DATA_BUF_SIZE); + if(file_buf == NULL) + { + printf("Cannot malloc the file data buf!"); + return -ERROR; + } + + if(ftp->upload_read == NULL) + { + return -ERROR; + } + + while(1) + { + if(EOK != ftp->upload_read(ftp, file_name, file_buf, ZFTP_FILE_DATA_BUF_SIZE, file_pos, &rd_len, &total_len)) + { + free(file_buf); + return -ERROR; + } + FD_ZERO(&writeset); + FD_SET(socket, &writeset); + if (select(socket + 1, NULL, &writeset, NULL, &timeout) <= 0) + { + free(file_buf); + printf("select data write socket timeout!"); + return -ERROR; + } + + // Wait and receive the packet back from the server. If n == -1, it failed. + if(rd_len != send(socket, (char*)file_buf, rd_len, 0)) + { + free(file_buf); + printf("reading data socket error!"); + return -ERROR; + } + + file_pos = file_pos + rd_len; + + if(file_pos >= total_len) + { + /*upload the file finish!*/ + break; + } + + } + + free(file_buf); + return EOK; + +} + + + +/********************************************************************************************************* +** Function name: zFTP_download_file_data() +** Descriptions: zFTP download the file data +** input parameters: socket, buf, buf_size, wait_time +** output parameters: rd_len +** Returned value: EOK, -ERROR +*********************************************************************************************************/ +static int zFTP_download_file_data(int socket, uint8_t *buf, uint32_t buf_size, + uint32_t *rd_len, uint32_t wait_time) +{ + struct timeval timeout; + fd_set readset; + int recv_len = 0; + + FD_ZERO(&readset); + + timeout.tv_sec = wait_time/1000; + timeout.tv_usec = 0; + + + FD_SET(socket, &readset); + if (select(socket + 1, &readset, NULL, NULL, &timeout) <= 0) + { + printf("select data socket timeout!"); + *rd_len = 0; + return -ERROR; + } + + // Wait and receive the packet back from the server. If n == -1, it failed. + recv_len = recv(socket, (char*)buf, buf_size, 0); + + if (recv_len < 0) + { + printf("reading data socket error!"); + return -ERROR; + } + else + { + *rd_len = recv_len; + return EOK; + } + +} + +/********************************************************************************************************* +** Function name: zFTP_download_send_cmd() +** Descriptions: zFTP send the download file command +** input parameters: 无 +** output parameters: 无 +** Returned value: 无 +*********************************************************************************************************/ +static int zFTP_download_send_cmd(int socket, char *cmd, uint32_t cmd_len, uint32_t *ack_code, + uint32_t *file_size, uint32_t wait_time) +{ + fd_set readset; + struct timeval timeout; + char ftp_recv_buf[100] = {0}; + int len = 0; + int code= 0; + int a= 0; + + if((NULL == ack_code) || (NULL == file_size) || + (NULL == cmd)) + { + return -ERROR; + } + + timeout.tv_sec = wait_time/1000; + timeout.tv_usec = 0; + + FD_ZERO(&readset); + FD_SET(socket, &readset); + + /*发送指令*/ + len = send(socket, cmd, cmd_len, 0); + + if (len < 0) { + printf("send cmd error!"); + return -ERROR; + } + + /*等待应答*/ + if (select(socket + 1, &readset, NULL, NULL, &timeout) <= 0) { + printf("select the socket timeout!"); + return -ETIMEOUT; + } + + // Wait and receive the packet back from the server. If n == -1, it failed. + len = recv(socket, (char*)ftp_recv_buf, sizeof(ftp_recv_buf), 0); + + if (len < 0) { + printf("reading from socket error!"); + return -ERROR; + } + + /*获取文件大小和应答码*/ + // if(2 == sscanf(ftp_recv_buf, "%d%*[^(](%d", &code,&a)) + // { + // *ack_code = code; + // *file_size = a; + // return EOK; + // } + if(1 == sscanf(ftp_recv_buf, "%d%*[^(](", &code)) + { + *ack_code = code; + // *file_size = a; //通过ftp zilla抓包分析,response中不含size + return EOK; + } + else + { + printf("Rcv data:%s\n", ftp_recv_buf); + return -ERROR; + } + + +} + + +/********************************************************************************************************* +** Function name: zFTP_quit() +** Descriptions: ftp logout and realse the zftp_client +** input parameters: ftp +** output parameters: None +** Returned value: EOK +*********************************************************************************************************/ +int zFTP_quit(zftp_client *ftp) +{ + uint32_t ack_code = 0; + char cmd_buf[50] = {0}; + + //ASSERT(ftp); + + /*退出登陆*/ + strcpy(cmd_buf, "QUIT\r\n"); + if((EOK != zFTP_send_cmd_wait_server_ack(ftp->control_socket, cmd_buf, strlen(cmd_buf), &ack_code, ZFTP_CMD_TIMEOUT)) || + (ack_code != 221)) + { + printf("Server logout error, ack_code:%d", ack_code); + + } + + closesocket(ftp->control_socket); + ftp->control_socket = -1; + + free(ftp); + + return EOK; +} + + +/********************************************************************************************************* +** Function name: zFTP_upload_file() +** Descriptions: upload the file to FTP server +** input parameters: ftp, path, file_name +** output parameters: file_size +** Returned value: zftp_client +*********************************************************************************************************/ +int zFTP_upload_file(zftp_client *ftp, char *file_name) +{ + char cmd_buf[50] = {0}; + uint32_t ack_code = 0; + int ret = EOK, fd = 0; + struct addrinfo hints, *addr_list = NULL, *cur = NULL; + uint16_t port = 0; + + //ASSERT(ftp); + + + /*Enter the pasv mode */ + if(EOK != zFTP_pasv_mode(ftp->control_socket, &ack_code, &port, ZFTP_CMD_TIMEOUT) || (ack_code != 227)) + { + printf("Enter pasv mode error, ack_code:%d", ack_code); + ret = -ERROR; + goto __exit; + } + + + /*creat the data socket link */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + sprintf(ftp->data_port, "%d", port); + + /* Do name resolution with both IPv6 and IPv4 */ + if (getaddrinfo(ftp->server_ip, ftp->data_port, &hints, &addr_list) != EOK) + { + goto __exit; + } + + for (cur = addr_list; cur != NULL; cur = cur->ai_next) + { + fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); + if (fd < 0) + { + continue; + } + + if (connect(fd, cur->ai_addr, cur->ai_addrlen) == 0) + { + ftp->data_socket = fd; + break; + } + + closesocket(fd); + + } + freeaddrinfo(addr_list); + + if(ftp->data_socket < 0) + { + ret = -ERROR; + goto __exit; + } + + /*send download the file command*/ + sprintf(cmd_buf, "STOR %s\r\n", file_name); + if((EOK != zFTP_send_cmd_wait_server_ack(ftp->control_socket, cmd_buf, strlen(cmd_buf), &ack_code, ZFTP_CMD_TIMEOUT)) || + (ack_code != 150)) + { + printf("upload file error, ack_code:%d", ack_code); + ret = -ERROR; + goto __exit; + } + + + /* read the file send to FTP server */ + if(EOK == zFTP_upload_file_data(ftp, file_name, ZFTP_CMD_TIMEOUT)) + { + + } + else + { + ret = -ERROR; + goto __exit; + } + + /*close the data socket*/ + if(ftp->data_socket >= 0) + { + closesocket(ftp->data_socket); + ftp->data_socket = -1; + } + + + + /*waite the upload file finish */ + if((EOK != zFTP_wait_server_ack(ftp->control_socket, &ack_code, ZFTP_CMD_TIMEOUT)) || (ack_code != 226)) + { + printf("Server not ack download complete, ack_code:%d", ack_code); + } + + ret = EOK; + +__exit: + if(ftp->data_socket >= 0) + { + closesocket(ftp->data_socket); + ftp->data_socket = -1; + } + + return ret; + +} + + + +/********************************************************************************************************* +** Function name: zFTP_download_file() +** Descriptions: download the file from FTP server +** input parameters: ftp, path, file_name +** output parameters: file_size +** Returned value: zftp_client +*********************************************************************************************************/ +int zFTP_download_file(zftp_client *ftp, char *file_name, int _file_size) +{ + char cmd_buf[50] = {0}; + uint32_t ack_code = 0; + int ret = EOK, fd = 0; + struct addrinfo hints, *addr_list = NULL, *cur = NULL; + uint32_t rd_len = 0; + uint8_t *file_buf = NULL; + uint32_t file_pos = 0; + uint16_t port = 0; + uint32_t file_size = _file_size; + + //ASSERT(ftp); + + file_buf = malloc(ZFTP_FILE_DATA_BUF_SIZE); + if(file_buf == NULL) + { + printf("Cannot malloc the file data buf!"); + return -ERROR; + } + + /*Enter the pasv mode */ + if(EOK != zFTP_pasv_mode(ftp->control_socket, &ack_code, &port, ZFTP_CMD_TIMEOUT) || (ack_code != 227)) + { + printf("Enter pasv mode error, ack_code:%d\n", ack_code); + ret = -ERROR; + goto __exit; + } + printf("Enter pasv mode, ack_code:%d\n", ack_code); + + + /*creat the data socket link */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + sprintf(ftp->data_port, "%d", port); + + /* Do name resolution with both IPv6 and IPv4 */ + if (getaddrinfo(ftp->server_ip, ftp->data_port, &hints, &addr_list) != EOK) + { + goto __exit; + } + + for (cur = addr_list; cur != NULL; cur = cur->ai_next) + { + fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); + if (fd < 0) + { + continue; + } + + if (connect(fd, cur->ai_addr, cur->ai_addrlen) == 0) + { + ftp->data_socket = fd; + break; + } + + closesocket(fd); + + } + freeaddrinfo(addr_list); + + if(ftp->data_socket < 0) + { + ret = -ERROR; + goto __exit; + } + + /*send download the file command*/ + sprintf(cmd_buf, "RETR %s\r\n", file_name); + if((EOK != zFTP_download_send_cmd(ftp->control_socket, cmd_buf, strlen(cmd_buf), &ack_code, &file_size, ZFTP_CMD_TIMEOUT)) || + (ack_code != 150)) + { + printf("Download file error, ack_code:%d\n", ack_code); + ret = -ERROR; + goto __exit; + } + printf("Download file, ack_code:%d\n", ack_code); + + /* read the file */ + while(file_size > file_pos) + { + if(EOK == zFTP_download_file_data(ftp->data_socket, file_buf, ZFTP_FILE_DATA_BUF_SIZE, &rd_len, ZFTP_CMD_TIMEOUT)) + { + if((rd_len) && (ftp->download_write)) + { + if(EOK != ftp->download_write(ftp, file_name, file_buf, rd_len, file_pos, file_size)) + { + ret = -ERROR; + goto __exit; + } + } + + } + else + { + ret = -ERROR; + goto __exit; + } + file_pos = file_pos + rd_len; + } + + /*waite the download file finish */ + if((EOK != zFTP_wait_server_ack(ftp->control_socket, &ack_code, ZFTP_CMD_TIMEOUT)) || (ack_code != 226) || (file_pos !=file_size )) + { + printf("Server not ack download complete, ack_code:%d\n", ack_code); + ret = ERROR; + } + else + { + printf("Server ack download complete, ack_code:%d\n", ack_code); + ret = EOK; + } + + +__exit: + if(ftp->data_socket >= 0) + { + closesocket(ftp->data_socket); + ftp->data_socket = -1; + } + + if(file_buf) + { + free(file_buf); + } + + return ret; + +} + + + +/********************************************************************************************************* +** Function name: zFTP_change_path() +** Descriptions: change the path of FTP server +** input parameters: ftp, path, path +** output parameters: file_size +** Returned value: zftp_client +*********************************************************************************************************/ +int zFTP_change_path(zftp_client *ftp, char *path) +{ + char cmd_buf[50] = {0}; + uint32_t ack_code = 0; + + //ASSERT(ftp); + //ASSERT(path); + + /*change path*/ + + sprintf(cmd_buf, "CWD %s\r\n", path); + if((EOK != zFTP_send_cmd_wait_server_ack(ftp->control_socket, cmd_buf, strlen(cmd_buf), &ack_code, ZFTP_CMD_TIMEOUT)) || + (ack_code != 250)) + { + printf("Switch dir error, ack_code:%d", ack_code); + return -ERROR; + + } + else + { + return EOK; + } + +} + + + +/********************************************************************************************************* +** Function name: zFTP_get_filesize() +** Descriptions: get the file size from FTP server +** input parameters: ftp, path, file_name +** output parameters: file_size +** Returned value: zftp_client +*********************************************************************************************************/ +int zFTP_get_filesize(zftp_client *ftp, char *file_name, uint32_t *file_size) +{ + char cmd_buf[50] = {0}; + uint32_t ack_code = 0; + + //ASSERT(ftp); + //ASSERT(file_name); + + + /*get the file size*/ + sprintf(cmd_buf, "SIZE %s\r\n", file_name); + if((EOK != zFTP_filesize_send_cmd(ftp->control_socket, cmd_buf, strlen(cmd_buf), &ack_code, file_size, ZFTP_CMD_TIMEOUT)) || + (ack_code != 213)) + { + printf("Get file size error, ack_code:%d", ack_code); + return -ERROR; + + } + else + { + printf("Get file size success, ack_code:%d, file size: %d\n", ack_code, *file_size); + return EOK; + } + +} + +/********************************************************************************************************* +** Function name: zFTP_set_callback() +** Descriptions: set the file download and upload callback function +** input parameters: ftp, dw_write, up_read, user_data +** output parameters: None +** Returned value: EOK +*********************************************************************************************************/ +int zFTP_set_callback(zftp_client *ftp, down_callback dw_write, up_callback up_read, void *user_data) +{ + //ASSERT(ftp); + + ftp->download_write = dw_write; + ftp->upload_read = up_read; + ftp->user_data = user_data; + + return EOK; +} + + +/********************************************************************************************************* +** Function name: zFTP_login() +** Descriptions: ftp login server +** input parameters: user_name, password, server_ip +** output parameters: None +** Returned value: zftp_client +*********************************************************************************************************/ +zftp_client *zFTP_login(char *user_name, char *password, char *server_ip) +{ + zftp_client *ftp = NULL; + int fd = -1; + uint32_t ack_code = 0; + char cmd_buf[50] = {0}; + struct addrinfo hints, *addr_list = NULL, *cur = NULL; + + + if((strlen(user_name) > ZFTP_USER_NAME_LEN) || (strlen(password) > ZFTP_PASSWORD_LEN) || + (strlen(server_ip) > ZFTP_SERVER_IP_LEN)) + { + return NULL; + } + + /*create a zftp client buf*/ + ftp = malloc(sizeof(zftp_client)); + + if(ftp) + { + memset(ftp, 0, sizeof(zftp_client)); + + ftp->data_socket = -1; + ftp->control_socket = -1; + + strncpy(ftp->user_name, user_name, strlen(user_name)); + strncpy(ftp->password, password, strlen(password)); + strncpy(ftp->server_ip, server_ip, strlen(server_ip)); + strncpy(ftp->control_port, ZFTP_SERVER_CONTROL_PORT, strlen(ZFTP_SERVER_CONTROL_PORT)); + + /*creat the control socket link */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + /* Do name resolution with both IPv6 and IPv4 */ + if (getaddrinfo(ftp->server_ip, ftp->control_port, &hints, &addr_list) != EOK) + { + goto __exit; + } + + for (cur = addr_list; cur != NULL; cur = cur->ai_next) + { + fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); + if (fd < 0) + { + continue; + } + + if (connect(fd, cur->ai_addr, cur->ai_addrlen) == 0) + { + ftp->control_socket = fd; + break; + } + + closesocket(fd); + } + + freeaddrinfo(addr_list); + + if(ftp->control_socket >= 0) + { + /* wait the login success and welcome*/ + if(EOK != zFTP_wait_server_ack(ftp->control_socket, &ack_code, ZFTP_CMD_TIMEOUT) || (ack_code != 220)) + { + printf("Server not ack welcome, ack_code:%d", ack_code); + goto __exit; + } + + /*input the user name */ + sprintf(cmd_buf, "USER %s\r\n", ftp->user_name); + if((EOK != zFTP_send_cmd_wait_server_ack(ftp->control_socket, cmd_buf, strlen(cmd_buf), &ack_code, ZFTP_CMD_TIMEOUT)) || + (ack_code != 331)) + { + printf("Login user error, ack_code:%d", ack_code); + goto __exit; + } + + /*input the password */ + sprintf(cmd_buf, "PASS %s\r\n", ftp->password); + if((EOK != zFTP_send_cmd_wait_server_ack(ftp->control_socket, cmd_buf, strlen(cmd_buf), &ack_code, ZFTP_CMD_TIMEOUT)) || + (ack_code != 230)) + { + printf("Login password error, ack_code:%d", ack_code); + goto __exit; + } + + /*change bin mode*/ + strcpy(cmd_buf, "TYPE I\r\n"); + if((EOK != zFTP_send_cmd_wait_server_ack(ftp->control_socket, cmd_buf, strlen(cmd_buf), &ack_code, ZFTP_CMD_TIMEOUT)) || + (ack_code != 200)) + { + printf("Switch bin mode error, ack_code:%d", ack_code); + goto __exit; + } + + return ftp; + } + } + else + { + printf("Cannot malloc the buf for zftp_client!"); + return NULL; + } + +__exit: + if(ftp->control_socket >= 0) + { + closesocket(ftp->control_socket); + } + + free(ftp); + ftp = NULL; + + return NULL; + +} +/********************************************************************************************************* +** End of file +*********************************************************************************************************/ + diff --git a/APP_Framework/Applications/app_test/test_ftpclient/libftp/libftp.h b/APP_Framework/Applications/app_test/test_ftpclient/libftp/libftp.h new file mode 100644 index 000000000..20eaeb454 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_ftpclient/libftp/libftp.h @@ -0,0 +1,142 @@ +/****************************************Copyright (c)**************************************************** +** fhqlongteng@163.com +** QQ:283669063 +**--------------File Info--------------------------------------------------------------------------------- +** File name: zFTP.h +** Last modified Date: 2020-12-01 +** Last Version: V1.00 +** Descriptions: FTPͨЭͷļ +** +**-------------------------------------------------------------------------------------------------------- +** Created by: Zhao shimin +** Created date: 2020-12-01 +** Version: V1.00 +** Descriptions: +** +**-------------------------------------------------------------------------------------------------------- +** Modified by: +** Modified date: +** Version: +** Descriptions: +** +** Rechecked by: +*********************************************************************************************************/ +#ifndef __zFTP_H_ +#define __zFTP_H_ + +#include + +/********************************************************************************************************* +* FTPĿͻ˵Ĵ洢Ļ +*********************************************************************************************************/ +#ifndef ZFTP_USER_NAME_LEN +#define ZFTP_USER_NAME_LEN 20 +#endif + +#ifndef ZFTP_PASSWORD_LEN +#define ZFTP_PASSWORD_LEN 20 +#endif + +#ifndef ZFTP_SERVER_IP_LEN +#define ZFTP_SERVER_IP_LEN 20 +#endif + +#ifndef ZFTP_FILE_DATA_BUF_SIZE +#define ZFTP_FILE_DATA_BUF_SIZE 400 +#endif + + +#define ZFTP_SERVER_CONTROL_PORT "21" +#define ZFTP_SERVER_DATA_PORT "22" + +/*FTP communicate command timeout, unit:ms */ +#define ZFTP_CMD_TIMEOUT 2000 + + +typedef int (*down_callback)(void * handle, char *file_name, uint8_t *buf, uint32_t len, uint32_t file_pos, uint32_t total_len); +typedef int (*up_callback)(void * handle, char *file_name, uint8_t *buf, uint32_t len, uint32_t file_pos, uint32_t *read_len, uint32_t *total_len); +/********************************************************************************************************* +* zFTPͨŹݽṹ +*********************************************************************************************************/ +typedef struct zftp_client_struct +{ + char user_name[ZFTP_USER_NAME_LEN]; + char password[ZFTP_PASSWORD_LEN]; + char server_ip[ZFTP_SERVER_IP_LEN]; + char data_port[6]; + char control_port[6]; + int control_socket; /* FTPsocket */ + int data_socket; /* FTPsocket */ + down_callback download_write; + up_callback upload_read; + void *user_data; + int errorno; + +}zftp_client; + +/********************************************************************************************************* +** Function name zFTP_login() +** Descriptions: ftp login server +** input parameters user_name, password, server_ip +** output parameters None +** Returned value: zftp_client +*********************************************************************************************************/ +zftp_client *zFTP_login(char *user_name, char *password, char *server_ip); + +/********************************************************************************************************* +** Function name zFTP_set_callback() +** Descriptions: set the file download and upload callback function +** input parameters ftp, dw_write, up_read, user_data +** output parameters None +** Returned value: RT_EOK +*********************************************************************************************************/ +int zFTP_set_callback(zftp_client *ftp, down_callback dw_write, up_callback up_read, void *user_data); + +/********************************************************************************************************* +** Function name zFTP_get_filesize() +** Descriptions: get the file size from FTP server +** input parameters ftp, path, file_name +** output parameters file_size +** Returned value: zftp_client +*********************************************************************************************************/ +int zFTP_get_filesize(zftp_client *ftp, char *file_name, uint32_t *file_size); + +/********************************************************************************************************* +** Function name zFTP_change_path() +** Descriptions: change the path of FTP server +** input parameters ftp, path, path +** output parameters file_size +** Returned value: zftp_client +*********************************************************************************************************/ +int zFTP_change_path(zftp_client *ftp, char *path); + +/********************************************************************************************************* +** Function name zFTP_download_file() +** Descriptions: download the file from FTP server +** input parameters ftp, path, file_name +** output parameters file_size +** Returned value: zftp_client +*********************************************************************************************************/ +int zFTP_download_file(zftp_client *ftp, char *file_name, int file_size); + +/********************************************************************************************************* +** Function name zFTP_upload_file() +** Descriptions: upload the file to FTP server +** input parameters ftp, path, file_name +** output parameters file_size +** Returned value: zftp_client +*********************************************************************************************************/ +int zFTP_upload_file(zftp_client *ftp, char *file_name); + +/********************************************************************************************************* +** Function name zFTP_quit() +** Descriptions: ftp logout and realse the zftp_client +** input parameters ftp +** output parameters None +** Returned value: RT_EOK +*********************************************************************************************************/ +int zFTP_quit(zftp_client *ftp); + + +#endif + diff --git a/APP_Framework/Applications/app_test/test_ftpclient/test_ftpclient.c b/APP_Framework/Applications/app_test/test_ftpclient/test_ftpclient.c new file mode 100644 index 000000000..1df536a8b --- /dev/null +++ b/APP_Framework/Applications/app_test/test_ftpclient/test_ftpclient.c @@ -0,0 +1,258 @@ +/****************************************Copyright (c)**************************************************** +** fhqlongteng@163.com +** QQ:283669063 +**--------------File Info--------------------------------------------------------------------------------- +** File name: zFTP_demo.c +** Last modified Date: 2020-12-01 +** Last Version: V1.00 +** Descriptions: zFTP demo +** +**-------------------------------------------------------------------------------------------------------- +** Created by: Zhao shimin +** Created date: 2020-12-01 +** Version: V1.00 +** Descriptions: +** +** +**-------------------------------------------------------------------------------------------------------- +** Modified by: +** Modified date: +** Version: +** Descriptions: +** +** Rechecked by: +*********************************************************************************************************/ +#include "./libftp/libftp.h" + +#ifdef ADD_XIZI_FEATURES +#include +#include +#include "lwip/sys.h" +#endif +#define PKG_USING_ZFTP 1 + +#ifdef PKG_USING_ZFTP + + +/********************************************************************************************************* +*       定义FTP的默认用户名称,服务器地址,端口等 +*********************************************************************************************************/ +#define FTP_SVR_ADDR "192.168.1.100" // +#define FTP_SVR_PATH "/" +#define FTP_USER_NAME "test" +#define FTP_PASSWORD "123456" +#define FTP_FILENAME "test.txt" +#define FIRMWARE_FLASH_PARTITION "firmware" +#define FIRMWARE_STORE_ADDR 0 + +static char tcp_demo_ipaddr[] = {192, 168, 1, 110}; +static char tcp_demo_netmask[] = {255, 255, 255, 0}; +static char tcp_demo_gwaddr[] = {192, 168, 1, 1}; + +/********************************************************************************************************* +** Function name: file_read() +** Descriptions: read file from flash +** input parameters: ftp, buf, len, file_pos, total_len +** output parameters: None +** Returned value: RT_OK, ERROR +*********************************************************************************************************/ +int file_read(void * handle, char *file_name, uint8_t *buf, uint32_t len, uint32_t file_pos, uint32_t *read_len, uint32_t *total_len) +{ + const struct fal_partition *partition = NULL; + + *total_len = 600 * 1024; + + // partition = fal_partition_find(FIRMWARE_FLASH_PARTITION); + if (partition == NULL) + { + // LOG_E("Find partition (%s) failed, Cannot save the net para!", FIRMWARE_FLASH_PARTITION); + return -ERROR; + } + + if(file_pos + len <= *total_len) + { + *read_len = len; + } + else + { + *read_len = *total_len - file_pos; + } + + // if(*read_len != fal_partition_read(partition, FIRMWARE_STORE_ADDR + file_pos, buf, *read_len)) + { + // LOG_E("write file error, file_pos = %d", file_pos); + } + + + return EOK; + + +} + + + +/********************************************************************************************************* +** Function name: file_write() +** Descriptions: write file into flash +** input parameters: ftp, buf, len, file_pos, total_len +** output parameters: None +** Returned value: RT_OK, ERROR +*********************************************************************************************************/ +int file_write(void * handle, char *file_name, uint8_t *buf, uint32_t len, uint32_t file_pos, uint32_t total_len) +{ + //open the file in sdcard + FILE* fp = fopen(file_name,"a+"); + if(fp == NULL){ + printf("file open error.\n"); + return -ERROR; + } + + //move to file pos to write + // if(fseek(fp, file_pos, SEEK_SET) != 0){ + // printf("fseek tp %d failed.\n", file_pos); + // } + int err_flag = fwrite(buf, sizeof(uint8_t),len,fp); + if(err_flag<0){ + printf("write failed,error:%d\n",err_flag); + return -ERROR; + } + printf("fwrite between %d to %d. \n", file_pos, file_pos+len); + + fclose(fp); + + return EOK; + + +} + +/********************************************************************************************************* +** Function name: file_write() +** Descriptions: write file into flash +** input parameters: ftp, buf, len, file_pos, total_len +** output parameters: None +** Returned value: RT_OK, ERROR +*********************************************************************************************************/ +int file_erase(uint32_t file_len) +{ + + + + return EOK; + + +} + + +/********************************************************************************************************* +** Function name: cmd_ftp_download() +** Descriptions: ftp download command line +** input parameters: argc, argv +** output parameters: None +** Returned value: RT_OK, ERROR +*********************************************************************************************************/ +int cmd_ftp_download(int argc, char **argv) +{ + lwip_config_tcp(0, tcp_demo_ipaddr, tcp_demo_netmask, tcp_demo_gwaddr); + + zftp_client *ftp; + uint32_t file_size = 0; + + + + ftp = zFTP_login(FTP_USER_NAME, FTP_PASSWORD, FTP_SVR_ADDR); + + if(ftp == NULL) + { + printf("zFTP login fail!\n"); + } + else + { + zFTP_set_callback(ftp, file_write, file_read, NULL); + + zFTP_change_path(ftp, FTP_SVR_PATH); + + if(strcmp(argv[2], "upload") == 0) + { + if(EOK == zFTP_upload_file(ftp, argv[1])) + { + printf("zFTP upload success!\n"); + } + else + { + printf("zFTP upload %s faile!\n", argv[1]); + } + } + else + { + if(EOK == zFTP_get_filesize(ftp, argv[1], &file_size)) + { + printf("zFTP file %s size:%d!\n", argv[1], file_size); + // file_erase(file_size); + fopen(argv[1], "w+"); //清除原文件内容,实现覆盖下载文件 + + if(EOK == zFTP_download_file(ftp, argv[1], file_size)) + { + printf("zFTP download success len: %d!\n", file_size); + } + + } + } + + zFTP_quit(ftp); + + } + + return 0; +} + +PRIV_SHELL_CMD_FUNCTION(cmd_ftp_download, a ftp client download sample, PRIV_SHELL_CMD_MAIN_ATTR); + + +void TestFtpFileDownload(){ + + lwip_config_tcp(0, tcp_demo_ipaddr, tcp_demo_netmask, tcp_demo_gwaddr); + zftp_client *ftp; + uint32_t file_size = 0; + uint32_t total_size = 0; + + + + ftp = zFTP_login(FTP_USER_NAME, FTP_PASSWORD, FTP_SVR_ADDR); + + if(ftp == NULL) + { + printf("zFTP login fail!\n"); + } + else + { + zFTP_set_callback(ftp, file_write, file_read, NULL); + zFTP_change_path(ftp, FTP_SVR_PATH); + for(int i=1; i<11; i++){ + char file_name[10] = ""; + sprintf(file_name, "%d.txt", i); + if(EOK == zFTP_get_filesize(ftp, file_name, &file_size)) + { + printf("zFTP file %s size:%d!\n", file_name, file_size); + fopen(file_name, "w+"); //清除原文件内容,实现覆盖下载文件 + + if(EOK == zFTP_download_file(ftp, file_name, file_size)) + { + printf("zFTP download success len: %d!\n", file_size); + } + total_size += file_size; + } + } + printf("All download finished. Total size: %d\n", total_size); + } + + zFTP_quit(ftp); +} +PRIV_SHELL_CMD_FUNCTION(TestFtpFileDownload, a ftp client test sample, PRIV_SHELL_CMD_MAIN_ATTR); + + + +/********************************************************************************************************* +** End of file +*********************************************************************************************************/ +#endif + diff --git a/APP_Framework/Applications/app_test/test_ftpclient/test_ftpclient.h b/APP_Framework/Applications/app_test/test_ftpclient/test_ftpclient.h new file mode 100644 index 000000000..e69de29bb