适配zftp,并初步完成文件下载功能与测试

This commit is contained in:
kkk 2023-07-29 21:56:09 +08:00
parent 20ffe20c36
commit 5ef5de3310
6 changed files with 1408 additions and 1 deletions

View File

@ -122,7 +122,7 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
endif endif
ifeq ($(CONFIG_USER_TEST_FTPCLIENT),y) ifeq ($(CONFIG_USER_TEST_FTPCLIENT),y)
SRC_FILES += SRC_FILES += test_ftpclient/test_ftpclient.c test_ftpclient/libftp/libftp.c
endif endif
ifeq ($(CONFIG_USER_TEST_LORA_P2P),y) ifeq ($(CONFIG_USER_TEST_LORA_P2P),y)

View File

@ -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

View File

@ -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 <sys_arch.h>
#include <lwip/sockets.h>
#include "lwip/sys.h"
#include <lwip/netdb.h>
#endif
#ifdef ADD_NUTTX_FEATURES
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#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
*********************************************************************************************************/

View File

@ -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 <transform.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 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; /* 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, 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

View File

@ -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 <sys_arch.h>
#include <lwip/sockets.h>
#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