diff --git a/APP_Framework/Applications/app_test/Makefile b/APP_Framework/Applications/app_test/Makefile index 6b0c1ea96..7f48ccbaa 100644 --- a/APP_Framework/Applications/app_test/Makefile +++ b/APP_Framework/Applications/app_test/Makefile @@ -134,7 +134,7 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y) endif ifeq ($(CONFIG_USER_TEST_FTPCLIENT),y) - SRC_FILES += + SRC_FILES += test_ftpclient/test_ftpclient.c endif ifeq ($(CONFIG_USER_TEST_LORA_P2P),y) diff --git a/APP_Framework/Applications/app_test/test_ftpclient/README.md b/APP_Framework/Applications/app_test/test_ftpclient/README.md new file mode 100644 index 000000000..0c70725fa --- /dev/null +++ b/APP_Framework/Applications/app_test/test_ftpclient/README.md @@ -0,0 +1,71 @@ +# 基于矽璓已实现的Lwip,在ARM上实现FTP协议的Client功能## + +## 1. 简介 +基于矽璓已实现的Lwip,在ARM上实现FTP协议的Client功能,实现文件的上传与下载。 +即基于XiZi内核移植支持FTP Client库,个人电脑中安装FTP服务端软件,充当FTP Server角色,在其上上传10个4KB文件,执行FTP协议的Client实现下载FTP Server上的10个文件。 + +## 2. 数据结构设计说明 +定义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; /* FTP控制socket */ + int data_socket; /* FTP数据socket */ + down_callback download_write; + up_callback upload_read; + void* user_data; + int errorno; + +}zftp_client; +``` +--------- +ftp登录函数 +``` +zftp_client* zFTP_login(char* user_name, char* password, char* server_ip); +``` +--------- +文件上传与回显 +``` +int zFTP_set_callback(zftp_client* ftp, down_callback dw_write, up_callback up_read, void* user_data); +``` +--------- +得到文件大小 +``` +int zFTP_get_filesize(zftp_client* ftp, char* file_name, rt_uint32_t* file_size); +``` +--------- +改变ftp服务器路径 +``` +int zFTP_change_path(zftp_client* ftp, char* path); +``` +--------- +从服务器下载文件 +``` +int zFTP_download_file(zftp_client* ftp, char* file_name); +``` +--------- +上传文件到ftp服务器 +``` +int zFTP_upload_file(zftp_client* ftp, char* file_name); +``` +--------- +退出登录并且停止服务器 +``` +int zFTP_quit(zftp_client* ftp); +``` +--------- +## 3. 测试程序说明 +测试了文件的上传与下载,FTP的TCP链接未建立成功 + +## 4. 运行结果(##需结合运行测试截图按步骤说明##) +编译,烧录bin文件 +![image](compile.png) +查看shell命令 +![image](command.png) +测试结果 +![image](test.png) + diff --git a/APP_Framework/Applications/app_test/test_ftpclient/command.png b/APP_Framework/Applications/app_test/test_ftpclient/command.png new file mode 100644 index 000000000..5791d746b Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient/command.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient/compile.png b/APP_Framework/Applications/app_test/test_ftpclient/compile.png new file mode 100644 index 000000000..4905b69da Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient/compile.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient/test.png b/APP_Framework/Applications/app_test/test_ftpclient/test.png new file mode 100644 index 000000000..ba9587e66 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient/test.png differ 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..19798e002 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_ftpclient/test_ftpclient.c @@ -0,0 +1,1033 @@ +/****************************************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: zck +** Modified date: 2023/10/05 +** Version: +** Descriptions: +** +** Rechecked by: +*********************************************************************************************************/ +// #include +// #include +// #include +// #include +#include +#include +#include +#include +#include"test_ftpclient.h" +#include "../lwip/sockets.h" +#include "sys_arch.h" + +#define DBG_ENABLE +#define DBG_SECTION_NAME "ftpclient" +#define DBG_LEVEL DBG_INFO +#define ERROR 1 +#define OK 0 + +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 +#define TCP_PROTOCAL 6 +#define TCP_PORT 21 +/********************************************************************************************************* +*       定义FTP的默认用户名称,服务器地址,端口等 +*********************************************************************************************************/ +#define FTP_SVR_ADDR "192.168.5.18" // "172.16.253.184" +#define FTP_USER_NAME "FTPs" +#define FTP_PASSWORD "123456" + +typedef int32_t rt_uint32_t; +typedef int16_t rt_uint16_t; +typedef int8_t rt_uint8_t; +/********************************************************************************************************* +** Function name: zFTP_wait_server_ack() +** Descriptions: FTP client wait server ack +** input parameters: socket, ack_code, wait_time +** output parameters: None +** Returned value: OK, -ERROR +*********************************************************************************************************/ +static int zFTP_wait_server_ack(int socket, rt_uint32_t* ack_code, rt_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; + } + return OK; + + + if (1 == sscanf(ftp_recv_buf, "%d", &code)) { + *ack_code = code; + return OK; + } + 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: OK, -ERROR +*********************************************************************************************************/ +static int zFTP_send_cmd_wait_server_ack(int socket, char* cmd, rt_uint32_t cmd_len, + rt_uint32_t* ack_code, rt_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 -1; + } + + // 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 OK; + } + 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, rt_uint32_t cmd_len, rt_uint32_t* ack_code, + rt_uint32_t* file_size, rt_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 -1; + } + + // 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 OK; + } + 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, rt_uint32_t* ack_code, rt_uint16_t* server_port, rt_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 -1; + } + + // 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 OK; + } + 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: OK, -ERROR +*********************************************************************************************************/ +static int zFTP_upload_file_data(zftp_client* ftp, char* file_name, rt_uint32_t wait_time) { + struct timeval timeout; + fd_set writeset; + int socket = -1; + rt_uint8_t* file_buf = NULL; + rt_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 (OK != 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 OK; + +} + + + +/********************************************************************************************************* +** 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: OK, -ERROR +*********************************************************************************************************/ +static int zFTP_download_file_data(int socket, rt_uint8_t* buf, rt_uint32_t buf_size, + rt_uint32_t* rd_len, rt_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 OK; + } + +} + +/********************************************************************************************************* +** 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, rt_uint32_t cmd_len, rt_uint32_t* ack_code, + rt_uint32_t* file_size, rt_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 -1; + } + + // 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; + } + return OK; + /*获取文件大小和应答码*/ + if (2 == sscanf(ftp_recv_buf, "%d%*[^(](%d", &code, &a)) { + *ack_code = code; + *file_size = a; + return OK; + } + else { + printf("Rcv data:%s", 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: OK +*********************************************************************************************************/ +int zFTP_quit(zftp_client* ftp) { + rt_uint32_t ack_code = 0; + char cmd_buf[50] = { 0 }; + + assert(ftp); + + /*退出登陆*/ + strcpy(cmd_buf, "QUIT\r\n"); + if ((OK != 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 OK; +} + + +/********************************************************************************************************* +** 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 }; + rt_uint32_t ack_code = 0; + int ret = OK, fd = 0; + struct sockaddr_in hints, * addr_list = NULL, * cur = NULL; + rt_uint16_t port = 0; + + assert(ftp); + + + /*Enter the pasv mode */ + if (OK != 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.sin_family = AF_UNSPEC; + hints.sin_port = htons(TCP_PORT); + hints.sin_addr.s_addr = INADDR_ANY; + sprintf(ftp->data_port, "%d", port); + + fd = socket(cur->sin_family, SOCK_STREAM, IPPROTO_TCP); + if (fd < 0) { + return -1; + } + + if (connect(fd, (const struct sockaddr*)&hints, sizeof(hints)) == 0) { + ftp->data_socket = fd; + + } + else { + return -1; + } + + if (ftp->data_socket < 0) { + ret = -ERROR; + goto __exit; + } + + /*send download the file command*/ + sprintf(cmd_buf, "STOR %s\r\n", file_name); + if ((OK != 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 (OK == 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 ((OK != 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 = OK; + +__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) { + char cmd_buf[50] = { 0 }; + rt_uint32_t ack_code = 0; + int ret = OK, fd = 0; + struct sockaddr_in hints, * addr_list = NULL, * cur = NULL; + rt_uint32_t rd_len = 0; + rt_uint8_t* file_buf = NULL; + rt_uint32_t file_pos = 0; + rt_uint16_t port = 0; + rt_uint32_t file_size = 0; + + 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 (OK != 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.sin_family = AF_UNSPEC; + hints.sin_port = htons(TCP_PORT); + hints.sin_addr.s_addr = INADDR_ANY; + sprintf(ftp->data_port, "%d", port); + + fd = socket(cur->sin_family, SOCK_STREAM, IPPROTO_TCP); + if (fd < 0) { + return -1; + } + + if (connect(fd, (const struct sockaddr*)&hints, sizeof(hints)) == 0) { + ftp->data_socket = fd; + } + else { + return -1; + } + + if (ftp->data_socket < 0) { + ret = -ERROR; + goto __exit; + } + + /*send download the file command*/ + sprintf(cmd_buf, "RETR %s\r\n", file_name); + if ((OK != 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", ack_code); + ret = -ERROR; + goto __exit; + } + + /* read the file */ + while (file_size > file_pos) { + if (OK == 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 (OK != 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 ((OK != 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", ack_code); + ret = ERROR; + } + else { + ret = OK; + } + + +__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 }; + rt_uint32_t ack_code = 0; + + assert(ftp); + assert(path); + + /*change path*/ + + sprintf(cmd_buf, "CWD %s\r\n", path); + if ((OK != 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 OK; + } + +} + + + +/********************************************************************************************************* +** 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, rt_uint32_t* file_size) { + char cmd_buf[50] = { 0 }; + rt_uint32_t ack_code = 0; + + assert(ftp); + assert(file_name); + + + /*get the file size*/ + sprintf(cmd_buf, "SIZE %s\r\n", file_name); + if ((OK != 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 { + return OK; + } + +} + +/********************************************************************************************************* +** 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: OK +*********************************************************************************************************/ +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 OK; +} + +/********************************************************************************************************* +** 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, rt_uint8_t* buf, rt_uint32_t len, rt_uint32_t file_pos, rt_uint32_t* read_len, rt_uint32_t* total_len) { + // const struct fal_partition* partition = NULL; + + // *total_len = 600 * 1024; + + // partition = fal_partition_find(FIRMWARE_FLASH_PARTITION); + // if (partition == NULL) { + // printf("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)) { + // printf("write file error, file_pos = %d", file_pos); + // } + + + return OK; + + +} + + + +/********************************************************************************************************* +** 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, rt_uint8_t* buf, rt_uint32_t len, rt_uint32_t file_pos, rt_uint32_t total_len) { + // int fd = open(FLASH_DEV_DRIVER, O_RDWR); + // if (fd < 0) { + // printf("fs fd open error:%d\n", fd); + // return; + // } + // struct BusBlockWriteParam flash_writer; + + // flash_writer.pos = file_pos; + // flash_writer.size = len; + // flash_writer.buffer = buf; + // // const struct fal_partition* partition = NULL; + // PrivWrite(fd, &flash_writer, NONE); + // struct BusBlockReadParam flash_reader; + // flash_reader.pos = 0x000000L; + // flash_reader.size = 8; + // flash_reader.buffer = read_buff; + + // PrivRead(fd, &flash_reader, NONE); + // printf("Read data is:"); + // for (int i = 0;i < flash_writer.size;i++) { + // printf("%02x ", read_buff[i]); + // read_buff[i]++; + // } + // printf("\n"); + // partition = fal_partition_find(FIRMWARE_FLASH_PARTITION); + // if (partition == NULL) { + // printf("Find partition (%s) failed, Cannot save the net para!", FIRMWARE_FLASH_PARTITION); + // return -ERROR; + // } + + // if (len != fal_partition_write(partition, FIRMWARE_STORE_ADDR + file_pos, buf, len)) { + // printf("write file error, file_pos = %d", file_pos); + // } + + + return OK; + + +} + +/********************************************************************************************************* +** Function name: file_erase() +** Descriptions: write file into flash +** input parameters: file_len +** output parameters: None +** Returned value: RT_OK, ERROR +*********************************************************************************************************/ +int file_erase(rt_uint32_t file_len) { + // const struct fal_partition* partition = NULL; + + // partition = fal_partition_find(FIRMWARE_FLASH_PARTITION); + // if (partition == NULL) { + // printf("Find partition (%s) failed, Cannot save the net para!", FIRMWARE_FLASH_PARTITION); + // return -ERROR; + // } + + // if (file_len != fal_partition_erase(partition, FIRMWARE_STORE_ADDR, file_len)) { + // printf("erase flash error"); + // } + + + return OK; + + +} +/********************************************************************************************************* +** 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; + rt_uint32_t ack_code = 0; + char cmd_buf[50] = { 0 }; + struct sockaddr_in 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.sin_family = AF_UNSPEC; + hints.sin_port = TCP_PORT; + hints.sin_addr.s_addr = inet_addr((char*)server_ip); + // /* Do name resolution with both IPv6 and IPv4 */ + // if (getaddrinfo(ftp->server_ip, ftp->control_port, &hints, &addr_list) != OK) { + // goto __exit; + // } + fd = socket(cur->sin_family, SOCK_STREAM, 21); + if (fd < 0) { + printf("socket error\n"); + return NULL; + } + + if (connect(fd, (const struct sockaddr*)&hints, sizeof(hints)) == 0) { + ftp->control_socket = fd; + } + else { + printf("connect error"); + return NULL; + } + + + if (ftp->control_socket >= 0) { + /* wait the login success and welcome*/ + if (OK != 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 ((OK != 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 ((OK != 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 ((OK != 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; + +} +void TestFTPClient(int args, char* argv[]) { + zftp_client* ftp; + rt_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 { + printf("zFTP login ss\n"); + printf("the four file will be upload to ftp server\n"); + printf("server ip:"); + printf("total file Memory:"); + + zFTP_set_callback(ftp, file_write, file_read, NULL); + if (strcmp(argv[2], "upload") == 0) { + if (OK == zFTP_upload_file(ftp, argv[1])) { + printf("zFTP upload success!\n"); + } + else { + printf("zFTP upload %s faile!\n", argv[1]); + } + } + else { + if (OK == zFTP_get_filesize(ftp, argv[1], &file_size)) { + printf("zFTP file %s size:%d!\n", argv[1], file_size); + file_erase(file_size); + + if (OK == zFTP_download_file(ftp, argv[1])) { + printf("zFTP download success len: %d!\n", file_size); + } + } + } + zFTP_quit(ftp); + } + return; +} +PRIV_SHELL_CMD_FUNCTION(TestFTPClient, Test socket using ftp client, PRIV_SHELL_CMD_MAIN_ATTR | SHELL_CMD_PARAM_NUM(8)); + 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..827241b74 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_ftpclient/test_ftpclient.h @@ -0,0 +1,128 @@ +/** + * @file test_ftpclient.h + * @author Zhao shimin + * @brief ftp + * @version 0.1 + * @date 2023-10-05 + * + * @copyright Copyright (c) 2023 + * from https://github.com/longtengmcu/zFTP/blob/master/inc/zFTP.h + */ + + + /********************************************************************************************************* + *       定义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 4096 //单位字节 +#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 int32_t rt_uint32_t; +typedef int16_t rt_uint16_t; +typedef int8_t rt_uint8_t; +typedef int (*down_callback)(void* handle, char* file_name, rt_uint8_t* buf, rt_uint32_t len, rt_uint32_t file_pos, rt_uint32_t total_len); +typedef int (*up_callback)(void* handle, char* file_name, rt_uint8_t* buf, rt_uint32_t len, rt_uint32_t file_pos, rt_uint32_t* read_len, rt_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; /* FTP控制socket */ + int data_socket; /* FTP数据socket */ + 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, rt_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); + +/********************************************************************************************************* +** 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); + + + +