796 lines
27 KiB
C
796 lines
27 KiB
C
#include "file_transfer.h"
|
||
#include "system/includes.h"
|
||
#include "system/fs/fs.h"
|
||
#include "btstack_3th_protocol_user.h"
|
||
#include "dev_manager.h"
|
||
|
||
#if (SMART_BOX_EN && TCFG_DEV_MANAGER_ENABLE)
|
||
|
||
#define FTP_FILE_DATA_UNIT (512) //(234)//不能超过RCSP协议的MTU大小
|
||
#define FTP_FILE_DATA_RECIEVE_REMAIN_SIZE (128) //接收缓存预留
|
||
#define FTP_FILE_DATA_RECIEVE_BUF_MIN_SIZE (FTP_FILE_DATA_UNIT + FTP_FILE_DATA_RECIEVE_REMAIN_SIZE)
|
||
#define FTP_FILE_DATA_RECIEVE_TIMEOUT (3*1000) //超时拉取数据等待时长, 超时时间到了,自动拉取
|
||
#define FTP_DOWNLOAD_FOLDER_NAME "downlad" //下载目录
|
||
#define FTP_FILE_VAILD_MARK "JL_FTP" //断点续传需要用到的文件内容标记
|
||
#define FTP_FILE_VAILD_MARK_TIMER_UNIT (10*1000) //单位ms
|
||
#define FTP_FILE_CRC_CAC_MAX_COUNTER (100) //文件校验一次校验的数据块个数
|
||
|
||
//#define FTP_DEBUG_ENABLE
|
||
#ifdef FTP_DEBUG_ENABLE
|
||
#define ftp_printf printf
|
||
#else
|
||
#define ftp_printf(...)
|
||
#endif//FTP_DEBUG_ENABLE
|
||
|
||
enum {
|
||
FTP_END_REASON_NONE = 0, //没有错误
|
||
FTP_END_REASON_WRITE_ERR, //写失败
|
||
FTP_END_REASON_DATA_OVER_LIMIT, //数据超范围
|
||
FTP_END_REASON_DATA_CRC_ERR, //文件校验失败
|
||
};
|
||
|
||
struct __file_check {
|
||
u16 crc_tmp;
|
||
u32 counter;
|
||
u32 remain;
|
||
};
|
||
|
||
|
||
struct __ftp_download {
|
||
u32 file_size;
|
||
u32 file_offset;
|
||
u8 win[FTP_FILE_DATA_UNIT];
|
||
u8 packet_id;
|
||
u8 packet_id_max;
|
||
u8 last_packet;
|
||
u16 mark_timer;
|
||
u16 get_timeout;
|
||
u16 start_timerout;
|
||
u16 file_crc;
|
||
struct __file_check check;
|
||
char *filepath;
|
||
FILE *file;
|
||
struct __dev *dev;
|
||
void (*end_callback)(void);
|
||
};
|
||
static struct __ftp_download *ftp_d = NULL;
|
||
|
||
static void file_transfer_download_get_data(void);
|
||
static void __file_transfer_download_file_check_caculate(void *priv);
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 校验分次处理消息发送处理
|
||
@param
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void file_transfer_download_file_check_continue(void)
|
||
{
|
||
int msg[4];
|
||
msg[0] = (int)__file_transfer_download_file_check_caculate;
|
||
msg[1] = 1;
|
||
msg[2] = 0;
|
||
os_taskq_post_type("app_core", Q_CALLBACK, 3, msg);
|
||
}
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 文件数据块crc校验
|
||
@param
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void __file_transfer_download_file_check_caculate(void *priv)
|
||
{
|
||
if (ftp_d == NULL) {
|
||
return ;
|
||
}
|
||
wdt_clear();
|
||
JL_ERR err = 0;
|
||
u32 cnt;
|
||
if (ftp_d->check.counter >= FTP_FILE_CRC_CAC_MAX_COUNTER) {
|
||
cnt = FTP_FILE_CRC_CAC_MAX_COUNTER;
|
||
} else {
|
||
cnt = ftp_d->check.counter;
|
||
}
|
||
printf("cnt = %d, check.counter = %d, crc_tmp = %x\n", cnt, ftp_d->check.counter, ftp_d->check.crc_tmp);
|
||
for (int i = 0; i < cnt; i++) {
|
||
fread(ftp_d->file, ftp_d->win, sizeof(ftp_d->win));
|
||
ftp_d->check.crc_tmp = CRC16_with_initval(ftp_d->win, sizeof(ftp_d->win), ftp_d->check.crc_tmp);
|
||
}
|
||
ftp_d->check.counter -= cnt;
|
||
if (ftp_d->check.counter == 0) {
|
||
if (ftp_d->check.remain) {
|
||
fread(ftp_d->file, ftp_d->win, ftp_d->check.remain);
|
||
printf("remain\n");
|
||
put_buf(ftp_d->win, ftp_d->check.remain);
|
||
ftp_d->check.crc_tmp = CRC16_with_initval(ftp_d->win, ftp_d->check.remain, ftp_d->check.crc_tmp);
|
||
}
|
||
//crc_check end
|
||
if (ftp_d->check.crc_tmp == ftp_d->file_crc) {
|
||
printf("crc check ok!!, start rename\n");
|
||
fseek(ftp_d->file, ftp_d->file_size, SEEK_SET);
|
||
//进入重命名流程
|
||
err = JL_CMD_send(JL_OPCODE_FILE_RENAME, NULL, 0, 1);
|
||
if (err) {
|
||
//命令发送失败, 直接停止
|
||
file_transfer_close();
|
||
}
|
||
return ;
|
||
} else {
|
||
printf("crc check fail, crc_tmp = %x, file_crc = %x!!\n", ftp_d->check.crc_tmp, ftp_d->file_crc);
|
||
u8 reason = FTP_END_REASON_DATA_CRC_ERR;
|
||
fdelete(ftp_d->file);
|
||
ftp_d->file = NULL;
|
||
JL_ERR err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER_END, &reason, 1, 1);
|
||
if (err) {
|
||
//命令发送失败, 直接停止
|
||
file_transfer_close();
|
||
}
|
||
}
|
||
} else {
|
||
file_transfer_download_file_check_continue();
|
||
}
|
||
}
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 文件文件校验处理
|
||
@param
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void file_transfer_download_file_check(void)
|
||
{
|
||
ftp_d->check.crc_tmp = 0;
|
||
ftp_d->check.counter = ftp_d->file_size / sizeof(ftp_d->win);
|
||
ftp_d->check.remain = ftp_d->file_size % sizeof(ftp_d->win);
|
||
ftp_d->file_offset = ftp_d->file_size;
|
||
printf("crc_tmp = %x, counter = %d, remain = %d\n", ftp_d->check.crc_tmp, ftp_d->check.counter, ftp_d->check.remain);
|
||
fseek(ftp_d->file, 0, SEEK_SET);
|
||
file_transfer_download_file_check_continue();
|
||
}
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 文件传输重命名
|
||
@param rename:重命名
|
||
@return
|
||
@note 此过程接收的数据是实际文件传输的内容
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static int file_rename(const char *rename)
|
||
{
|
||
if (ftp_d && ftp_d->file) {
|
||
//rename之前先关闭文件
|
||
fclose(ftp_d->file);
|
||
ftp_d->file = NULL;
|
||
//重新打开文件
|
||
//printf("ftp_d->filepath:%s, rename:%s\n", ftp_d->filepath, rename);
|
||
ftp_d->file = fopen(ftp_d->filepath, "r");
|
||
//free(path);
|
||
if (ftp_d->file) {
|
||
//文件打开成功, 重命名
|
||
int ret = frename(ftp_d->file, rename);
|
||
if (ret) {
|
||
printf("rename fail\n");
|
||
} else {
|
||
printf("rename ok\n");
|
||
}
|
||
return ret;
|
||
} else {
|
||
printf("rename file open err!!");
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 文件重传文件头信息保存处理
|
||
@param file:文件句柄,win:临时缓存,offset:文件偏移
|
||
@return
|
||
@note 文件传输过程, 定时会触发断点续传信息保存处理
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void file_transfer_download_vaild_mark_fill(FILE *file, u8 *win, u32 offset)
|
||
{
|
||
if (file) {
|
||
fseek(file, 0, SEEK_SET);
|
||
memset(win, 0, FTP_FILE_DATA_UNIT);
|
||
memcpy(win, FTP_FILE_VAILD_MARK, strlen(FTP_FILE_VAILD_MARK));
|
||
memcpy(win + strlen(FTP_FILE_VAILD_MARK), &offset, sizeof(offset));
|
||
fwrite(file, win, FTP_FILE_DATA_UNIT);
|
||
fseek(file, offset, SEEK_SET);
|
||
printf("============================================%s, offset = %d\n", __FUNCTION__, offset);
|
||
}
|
||
}
|
||
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 断点续传信息解析处理
|
||
@param file:文件句柄, 文件偏移获取指针
|
||
@return
|
||
@note 在文件传输开始的时候进行解析, 目的是找到续传文件偏移
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void file_transfer_download_intermittent_parse(FILE *file, u32 *offset)
|
||
{
|
||
if (file) {
|
||
char mark[10] = {0};
|
||
fseek(file, 0, SEEK_SET);
|
||
int rlen = fread(file, mark, strlen(FTP_FILE_VAILD_MARK));
|
||
if (rlen) {
|
||
if (strcmp(mark, FTP_FILE_VAILD_MARK) == 0) {
|
||
printf("find VAILD_MARK !!\n");
|
||
rlen = fread(file, offset, sizeof(u32));
|
||
if (rlen) {
|
||
printf("read offset ok, %d!!\n", *offset);
|
||
fseek(file, *offset, SEEK_SET);
|
||
} else {
|
||
printf("read offset fail!!\n");
|
||
*offset = 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 文件下载数据拉取超时处理
|
||
@param priv:私有参数,
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void file_transfer_download_get_timeout(void *priv)
|
||
{
|
||
ftp_printf("timeout!!!\n");
|
||
//在超时时间内没有收完所需要的数据, 重新拉取数据
|
||
file_transfer_download_get_data();
|
||
}
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 断点续传定时保存处理
|
||
@param
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void file_transfer_download_vaild_mark_scan(void *priv)
|
||
{
|
||
if (ftp_d && ftp_d->file && ftp_d->mark_timer && ftp_d->last_packet == 0) {
|
||
file_transfer_download_vaild_mark_fill(ftp_d->file, ftp_d->win, ftp_d->file_offset);
|
||
}
|
||
}
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 文件下载数据拉取处理
|
||
@param 无
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void file_transfer_download_get_data(void)
|
||
{
|
||
if (ftp_d == NULL || ftp_d->file == NULL) {
|
||
ftp_printf("file not ready %d!!\n", __LINE__);
|
||
return;
|
||
}
|
||
|
||
u32 file_offset = 0;
|
||
u16 recieve_max = rcsp_packet_write_alloc_len();
|
||
if (recieve_max < FTP_FILE_DATA_RECIEVE_BUF_MIN_SIZE) {
|
||
ftp_printf("not enough buf to recieve!!\n");
|
||
return;
|
||
} else {
|
||
///预留些接收缓存给其他通信使用
|
||
recieve_max -= FTP_FILE_DATA_RECIEVE_REMAIN_SIZE;
|
||
}
|
||
|
||
ftp_d->packet_id = 0;
|
||
ftp_d->packet_id_max = recieve_max / FTP_FILE_DATA_UNIT;
|
||
recieve_max = ftp_d->packet_id_max * FTP_FILE_DATA_UNIT;
|
||
|
||
if (ftp_d->last_packet) {
|
||
recieve_max = FTP_FILE_DATA_UNIT;
|
||
file_offset = 0;
|
||
} else {
|
||
file_offset = ftp_d->file_offset;
|
||
}
|
||
ftp_printf("[get]recieve_max:%d, file_offset %d\n", recieve_max, file_offset);
|
||
u8 parm[7] = {0};
|
||
parm[0] = 0;
|
||
WRITE_BIG_U16(parm + 1, recieve_max);
|
||
WRITE_BIG_U32(parm + 3, file_offset);
|
||
JL_ERR err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER, parm, sizeof(parm), 0);
|
||
if (err) {
|
||
ftp_printf("%s fail!!! %d\n", __FUNCTION__, err);
|
||
return;
|
||
}
|
||
if (ftp_d->get_timeout == 0) {
|
||
ftp_d->get_timeout = sys_timeout_add(NULL, file_transfer_download_get_timeout, FTP_FILE_DATA_RECIEVE_TIMEOUT);
|
||
}
|
||
return;
|
||
}
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 文件路径长度统计
|
||
@param root_path:根目录, folder:文件夹,filename:文件名
|
||
@return 文件路径长度
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static u32 creat_path_len(char *root_path, const char *folder, u8 *name, u16 name_len)
|
||
{
|
||
return (strlen(root_path) + strlen(folder) + name_len + strlen("/") + 1);
|
||
}
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 文件路径组装处理
|
||
@param
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void creat_file_path(char *path, char *root_path, const char *folder, u8 *name, u16 name_len)
|
||
{
|
||
strcat(path, root_path);
|
||
strcat(path, folder);
|
||
strcat(path, "/");
|
||
//strcat(path, name);
|
||
memcpy(path + strlen(root_path) + strlen(folder) + 1, name, name_len);
|
||
//printf("path = %s\n", path);
|
||
}
|
||
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 文件下载开始
|
||
@param OpCode_SN:数据包序列号,data:数据, len:数据长度
|
||
@return 文件路径长度
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void file_transfer_download_start(u8 OpCode_SN, u8 *data, u16 len)
|
||
{
|
||
if (ftp_d) {
|
||
//收到了文件传输开始命令, 停止启动超时处理
|
||
if (ftp_d->start_timerout) {
|
||
sys_timeout_del(ftp_d->start_timerout);
|
||
ftp_d->start_timerout = 0;
|
||
}
|
||
}
|
||
|
||
JL_ERR err = 0;
|
||
///创建文件
|
||
u32 file_size = READ_BIG_U32(data);//占用4byte
|
||
u16 file_crc = READ_BIG_U16(data + 4);//占用2byte
|
||
u8 *file_name = data + 4 + 2;
|
||
u16 file_name_len = len - 6;
|
||
if (ftp_d == NULL) {
|
||
ftp_d = zalloc(sizeof(struct __ftp_download));
|
||
if (ftp_d) {
|
||
printf("%s, no mem\n", __FUNCTION__);
|
||
JL_CMD_response_send(JL_OPCODE_FILE_TRANSFER_START, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0);
|
||
return ;
|
||
}
|
||
}
|
||
|
||
ftp_printf("file_size = %d, file_crc = %x\n", file_size, file_crc);
|
||
|
||
struct __dev *dev = dev_manager_find_active(0);
|
||
if (!dev) {
|
||
file_transfer_close();
|
||
ftp_printf("no dev online !!\n");
|
||
JL_CMD_response_send(JL_OPCODE_FILE_TRANSFER_START, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0);
|
||
return ;
|
||
}
|
||
char *root_path = dev_manager_get_root_path(dev);
|
||
char *folder = FTP_DOWNLOAD_FOLDER_NAME;
|
||
char *path = zalloc(creat_path_len(root_path, folder, file_name, file_name_len));
|
||
|
||
u8 new_file = 0;
|
||
ASSERT(path);
|
||
creat_file_path(path, root_path, folder, file_name, file_name_len);
|
||
ftp_d->file = fopen(path, "r");
|
||
if (ftp_d->file) {
|
||
printf("file exist\n");
|
||
new_file = 0;
|
||
fclose(ftp_d->file);
|
||
ftp_d->file = NULL;
|
||
} else {
|
||
printf("file new\n");
|
||
new_file = 1;
|
||
}
|
||
|
||
ftp_d->file = fopen(path, "w+");
|
||
ftp_d->filepath = path;
|
||
//free(path);
|
||
if (ftp_d->file == NULL) {
|
||
ftp_printf("file create err\n");
|
||
file_transfer_close();
|
||
///文件打开失败, 回复APP文件传输失败
|
||
JL_CMD_response_send(JL_OPCODE_FILE_TRANSFER_START, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0);
|
||
return ;
|
||
}
|
||
ftp_d->dev = dev;
|
||
ftp_d->file_offset = 0;
|
||
ftp_d->file_crc = file_crc;
|
||
ftp_d->last_packet = 0;
|
||
ftp_d->file_size = file_size;
|
||
if (ftp_d->file_size > sizeof(ftp_d->win)) {
|
||
if (new_file == 0) {
|
||
///解析断点续传的文件偏移
|
||
file_transfer_download_intermittent_parse(ftp_d->file, &ftp_d->file_offset);
|
||
}
|
||
if (ftp_d->file_offset == 0 || ftp_d->file_offset > file_size) {
|
||
printf("file offset err !! reset offset \n");
|
||
ftp_d->file_offset = sizeof(ftp_d->win);
|
||
file_transfer_download_vaild_mark_fill(ftp_d->file, ftp_d->win, ftp_d->file_offset);
|
||
} else if (ftp_d->file_offset == file_size) {
|
||
//上次文件已经收完, 进入校验流程
|
||
printf("file aready download end \n");
|
||
file_transfer_download_file_check();
|
||
return ;
|
||
}
|
||
} else {
|
||
ftp_d->last_packet = 1;
|
||
}
|
||
///回复APP文件传输准备就绪
|
||
u16 file_data_unit = 0;
|
||
WRITE_BIG_U16(&file_data_unit, FTP_FILE_DATA_UNIT);
|
||
err = JL_CMD_response_send(JL_OPCODE_FILE_TRANSFER_START, JL_PRO_STATUS_SUCCESS, OpCode_SN, (u8 *)&file_data_unit, sizeof(u16));
|
||
if (err == 0) {
|
||
printf("%s ok!! file_offset: %d, data unit = %d\n", __FUNCTION__, ftp_d->file_offset, FTP_FILE_DATA_UNIT);
|
||
///回复启动成功之后,启动数据拉取操作(这里是第一次)
|
||
//fseek(ftp_d->file, ftp_d->file_offset, SEEK_SET);//重定位下文件位置
|
||
file_transfer_download_get_data();
|
||
ftp_d->mark_timer = sys_timer_add(NULL, file_transfer_download_vaild_mark_scan, FTP_FILE_VAILD_MARK_TIMER_UNIT);
|
||
return ;
|
||
} else {
|
||
ftp_printf("%s resp fail!!\n", __FUNCTION__);
|
||
file_transfer_close();
|
||
ftp_d = NULL;
|
||
}
|
||
return;
|
||
}
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 文件传输, 重命名处理
|
||
@param
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void file_transfer_file_rename(u8 status, u8 *data, u16 len)
|
||
{
|
||
if (ftp_d) {
|
||
if (status == JL_PRO_STATUS_SUCCESS) {
|
||
printf("%s !!, %d\n", __FUNCTION__, __LINE__);
|
||
put_buf(data, len);
|
||
//重命名
|
||
if (file_rename((const char *)data) == 0) {
|
||
u8 reason = FTP_END_REASON_NONE;
|
||
int err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER_END, &reason, 1, 1);
|
||
if (err) {
|
||
file_transfer_close();
|
||
}
|
||
dev_manager_set_valid(ftp_d->dev, 1);
|
||
} else {
|
||
//有重名的, 重新获取新名称, 如:“xxx_n.mp3”,n为数字
|
||
int err = JL_CMD_send(JL_OPCODE_FILE_RENAME, NULL, 0, 1);
|
||
if (err) {
|
||
file_transfer_close();
|
||
}
|
||
}
|
||
} else {
|
||
ftp_printf("%s fail!! %d\n", __FUNCTION__, status);
|
||
if (ftp_d->file) {
|
||
//重命名失败,删除文件
|
||
printf("renam file fail, delete file\n");
|
||
fdelete(ftp_d->file);
|
||
ftp_d->file = NULL;
|
||
}
|
||
file_transfer_close();
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 文件下载结束(F->A的回复处理)
|
||
@param status:命令执行状态,data:数据, len:数据长度
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void file_transfer_download_end(u8 status, u8 *data, u16 len)
|
||
{
|
||
if (ftp_d) {
|
||
ftp_printf("%s status %d\n", __FUNCTION__, status);
|
||
file_transfer_close();
|
||
}
|
||
}
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 文件传输,最后一包数据接收处理
|
||
@param data:数据内容 len:数据长度
|
||
@return
|
||
@note 文件传输流程是最后才写文件第一包数据
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void file_transfer_download_doing_last_packet(u8 *data, u16 len)
|
||
{
|
||
u8 reason = FTP_END_REASON_NONE;
|
||
JL_ERR err = 0;
|
||
if (len > FTP_FILE_DATA_UNIT) {
|
||
printf("last packet data len err!!\n");
|
||
reason = FTP_END_REASON_DATA_OVER_LIMIT;
|
||
err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER_END, &reason, 1, 1);
|
||
if (err) {
|
||
//命令发送失败, 直接停止
|
||
file_transfer_close();
|
||
}
|
||
return ;
|
||
}
|
||
if (ftp_d->get_timeout) {
|
||
sys_timeout_del(ftp_d->get_timeout);
|
||
ftp_d->get_timeout = 0;
|
||
}
|
||
printf("get last packet ok\n");
|
||
fseek(ftp_d->file, 0, SEEK_SET);
|
||
int wlen = fwrite(ftp_d->file, data, len);
|
||
if (wlen != len) {
|
||
ftp_printf("%s err !! %d\n", __FUNCTION__, wlen);
|
||
reason = FTP_END_REASON_WRITE_ERR;//文件写异常
|
||
err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER_END, &reason, 1, 1);
|
||
if (err) {
|
||
//命令发送失败, 直接停止
|
||
file_transfer_close();
|
||
}
|
||
} else {
|
||
//文件接收完成,文件校验
|
||
file_transfer_download_file_check();
|
||
}
|
||
//fseek(ftp_d->file, ftp_d->file_offset, SEEK_SET);
|
||
}
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 文件传输过程处理(A->F)
|
||
@param data:数据, len:数据长度
|
||
@return
|
||
@note 此过程接收的数据是实际文件传输的内容
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void file_transfer_download_doing(u8 *data, u16 len)
|
||
{
|
||
if (ftp_d && ftp_d->file) {
|
||
ftp_printf("id = %d, len = %d\n", data[0], len - 1);
|
||
|
||
if (ftp_d->packet_id != data[0]) {
|
||
ftp_printf("warning !! packet_id err %d, %d\n", ftp_d->packet_id, data[0]);
|
||
return ;
|
||
}
|
||
len -= 1;
|
||
data += 1;
|
||
ftp_d->packet_id ++;
|
||
u8 reason = FTP_END_REASON_NONE;
|
||
int wlen = 0;
|
||
JL_ERR err = 0;
|
||
|
||
if (ftp_d->last_packet) {
|
||
file_transfer_download_doing_last_packet(data, len);
|
||
return ;
|
||
}
|
||
|
||
if (ftp_d->file_offset >= ftp_d->file_size) {
|
||
printf("err, file data is over limit!!\n");
|
||
reason = FTP_END_REASON_DATA_OVER_LIMIT;//数据超范围
|
||
err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER_END, &reason, 1, 1);
|
||
if (err) {
|
||
//命令发送失败, 直接停止
|
||
file_transfer_close();
|
||
}
|
||
return ;
|
||
}
|
||
|
||
wlen = fwrite(ftp_d->file, data, len);
|
||
if (wlen != len) {
|
||
ftp_printf("%s err !! %d\n", __FUNCTION__, wlen);
|
||
reason = FTP_END_REASON_WRITE_ERR;//文件写异常
|
||
err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER_END, &reason, 1, 1);
|
||
if (err) {
|
||
//命令发送失败, 直接停止
|
||
file_transfer_close();
|
||
}
|
||
} else {
|
||
if (len != FTP_FILE_DATA_UNIT) {
|
||
ftp_printf("data is not a normal unit !!\n");
|
||
}
|
||
ftp_d->file_offset += len;
|
||
ftp_printf("ftp_d->file_offset:%d, ftp_d->file_size:%d, len:%d\n", ftp_d->file_offset, ftp_d->file_size, len);
|
||
if (ftp_d->file_offset >= ftp_d->file_size) {
|
||
ftp_printf("file recieve end!! get file first packet\n");
|
||
if (ftp_d->mark_timer) {
|
||
sys_timer_del(ftp_d->mark_timer);
|
||
ftp_d->mark_timer = 0;
|
||
}
|
||
ftp_d->last_packet = 1;
|
||
file_transfer_download_get_data();
|
||
return;
|
||
}
|
||
ftp_d->last_packet = 0;
|
||
if (ftp_d->get_timeout) {
|
||
//接收数据成功,重置一下超时
|
||
ftp_printf("reset timeout!!\n");
|
||
sys_timer_modify(ftp_d->get_timeout, FTP_FILE_DATA_RECIEVE_TIMEOUT);
|
||
}
|
||
if (ftp_d->packet_id >= ftp_d->packet_id_max) {
|
||
//该次数据包已经收完,拉取新的数据
|
||
ftp_printf("get more!!\n");
|
||
file_transfer_download_get_data();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 文件传输,被动取消处理
|
||
@param OpCode_SN:数据包sn码, 回复的时候用的
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void file_transfer_download_passive_cancel(u8 OpCode_SN, u8 *data, u16 len)
|
||
{
|
||
file_transfer_close();
|
||
printf("passive_cancel answer\n");
|
||
JL_CMD_response_send(JL_OPCODE_FILE_TRANSFER_CANCEL, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0);
|
||
}
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 文件传输,主动取消处理
|
||
@param
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void file_transfer_download_active_cancel(void)
|
||
{
|
||
if (ftp_d) {
|
||
file_transfer_close();
|
||
JL_CMD_send(JL_OPCODE_FILE_TRANSFER_CANCEL, NULL, 0, 1);
|
||
}
|
||
}
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 文件传输,主动取消处理回复处理
|
||
@param
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void file_transfer_download_active_cancel_response(u8 status, u8 *data, u16 len)
|
||
{
|
||
if (status == JL_PRO_STATUS_SUCCESS) {
|
||
printf("active_cancel_response ok!!");
|
||
}
|
||
}
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 文件传输关闭处理
|
||
@param
|
||
@return
|
||
@note 主要是做一些资源释放处理
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void file_transfer_close(void)
|
||
{
|
||
if (ftp_d) {
|
||
if (ftp_d->check.counter) {
|
||
printf("crc caculating !! close err\n");
|
||
return ;
|
||
}
|
||
if (ftp_d->start_timerout) {
|
||
sys_timeout_del(ftp_d->start_timerout);
|
||
ftp_d->start_timerout = 0;
|
||
}
|
||
if (ftp_d->get_timeout) {
|
||
sys_timeout_del(ftp_d->get_timeout);
|
||
ftp_d->get_timeout = 0;
|
||
}
|
||
if (ftp_d->mark_timer) {
|
||
sys_timer_del(ftp_d->mark_timer);
|
||
ftp_d->mark_timer = 0;
|
||
}
|
||
if (ftp_d->file) {
|
||
if (ftp_d->last_packet == 0) {
|
||
//文件没有传输完, 如果不是直接断电, 有机会执行更新断点续传的文件偏移信息
|
||
file_transfer_download_vaild_mark_fill(ftp_d->file, ftp_d->win, ftp_d->file_offset);
|
||
}
|
||
fclose(ftp_d->file);
|
||
}
|
||
if (ftp_d->filepath) {
|
||
free(ftp_d->filepath);
|
||
}
|
||
if (ftp_d->end_callback) {
|
||
ftp_d->end_callback();
|
||
}
|
||
free(ftp_d);
|
||
ftp_d = NULL;
|
||
printf("file_transfer_close!!!!!!\n");
|
||
}
|
||
}
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 文件传输启动超时处理
|
||
@param
|
||
@return
|
||
@note 响应app预处理,之后在设定时间内没有发文件传输开始命令过来触发超时
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void file_transfer_start_timeout(void)
|
||
{
|
||
printf("%s\n", __FUNCTION__);
|
||
file_transfer_close();
|
||
}
|
||
|
||
|
||
//*----------------------------------------------------------------------------*/
|
||
/**@brief 文件传输初始化处理
|
||
@param end_callback:文件传输结束处理回调
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void file_transfer_init(void (*end_callback)(void))
|
||
{
|
||
if (ftp_d) {
|
||
ftp_printf("file downloading err %d!!\n", __LINE__);
|
||
return ;
|
||
}
|
||
ftp_d = zalloc(sizeof(struct __ftp_download));
|
||
if (ftp_d == NULL) {
|
||
if (end_callback) {
|
||
end_callback();
|
||
}
|
||
return ;
|
||
}
|
||
ftp_d->end_callback = end_callback;
|
||
//如果在超时时间内都没有发文件传输开始命令, 退出文件传输流程
|
||
ftp_d->start_timerout = sys_timeout_add(NULL, file_transfer_start_timeout, 2000);
|
||
}
|
||
#else
|
||
|
||
void file_transfer_init(void (*end_callback)(void))
|
||
{
|
||
}
|
||
void file_transfer_download_start(u8 OpCode_SN, u8 *data, u16 len)
|
||
{
|
||
}
|
||
void file_transfer_download_end(u8 status, u8 *data, u16 len)
|
||
{
|
||
}
|
||
void file_transfer_download_doing(u8 *data, u16 len)
|
||
{
|
||
}
|
||
void file_transfer_download_passive_cancel(u8 OpCode_SN, u8 *data, u16 len)
|
||
{
|
||
}
|
||
void file_transfer_download_active_cancel(void)
|
||
{
|
||
}
|
||
void file_transfer_download_active_cancel_response(u8 status, u8 *data, u16 len)
|
||
{
|
||
}
|
||
void file_transfer_file_rename(u8 status, u8 *data, u16 len)
|
||
{
|
||
}
|
||
void file_transfer_close(void)
|
||
{
|
||
}
|
||
|
||
#endif
|
||
|
||
|
||
|