diff --git a/project/example_luatos_ftp/inc/RTE_device.h b/project/example_luatos_ftp/inc/RTE_device.h new file mode 100644 index 00000000..5d9c31d9 --- /dev/null +++ b/project/example_luatos_ftp/inc/RTE_device.h @@ -0,0 +1,354 @@ +#ifndef __RTE_DEVICE_H +#define __RTE_DEVICE_H + +#include "ec618.h" + +/* Peripheral IO Mode Select, Must Configure First !!! + Note, when receiver works in DMA_MODE, interrupt is also enabled to transfer tailing bytes. +*/ + +#define POLLING_MODE 0x1 +#define DMA_MODE 0x2 +#define IRQ_MODE 0x3 +#define UNILOG_MODE 0x4 + +#define RTE_UART0_TX_IO_MODE UNILOG_MODE +#define RTE_UART0_RX_IO_MODE IRQ_MODE +#define USART0_RX_TRIG_LVL (30) + +#define RTE_UART1_TX_IO_MODE DMA_MODE +#define RTE_UART1_RX_IO_MODE DMA_MODE + +#define RTE_UART2_TX_IO_MODE POLLING_MODE +#define RTE_UART2_RX_IO_MODE DMA_MODE + +#define RTE_SPI0_IO_MODE POLLING_MODE + +#define RTE_SPI1_IO_MODE POLLING_MODE + +#define RTE_I2C0_IO_MODE POLLING_MODE +#define RTE_I2C1_IO_MODE POLLING_MODE + + +// I2C0 (Inter-integrated Circuit Interface) [Driver_I2C0] +// Configuration settings for Driver_I2C0 in component ::Drivers:I2C +#define RTE_I2C0 1 + +// { PAD_PIN28}, // 0 : gpio13 / 2 : I2C0 SCL +// { PAD_PIN27}, // 0 : gpio12 / 2 : I2C0 SDA +#define RTE_I2C0_SCL_BIT 28 // AUDIO use 28 +#define RTE_I2C0_SCL_FUNC PAD_MUX_ALT2 + +#define RTE_I2C0_SDA_BIT 27 // AUDIO use 27 +#define RTE_I2C0_SDA_FUNC PAD_MUX_ALT2 + +// DMA +// Tx +// Channel <0=>0 <1=>1 <2=>2 <3=>3 <4=>4 <5=>5 <6=>6 <7=>7 +#define RTE_I2C0_DMA_TX_EN 0 +#define RTE_I2C0_DMA_TX_REQID DMA_REQUEST_I2C0_TX +// Rx +// Channel <0=>0 <1=>1 <2=>2 <3=>3 <4=>4 <5=>5 <6=>6 <7=>7 +#define RTE_I2C0_DMA_RX_EN 0 +#define RTE_I2C0_DMA_RX_REQID DMA_REQUEST_I2C0_RX + +// I2C1 (Inter-integrated Circuit Interface) [Driver_I2C1] +// Configuration settings for Driver_I2C1 in component ::Drivers:I2C +#define RTE_I2C1 1 + +// { PAD_PIN20}, // 0 : gpio5 / 2 : I2C1 SCL +// { PAD_PIN19}, // 0 : gpio4 / 2 : I2C1 SDA +#define RTE_I2C1_SCL_BIT 20 +#define RTE_I2C1_SCL_FUNC PAD_MUX_ALT2 + +#define RTE_I2C1_SDA_BIT 19 +#define RTE_I2C1_SDA_FUNC PAD_MUX_ALT2 + +// DMA +// Tx +// Channel <0=>0 <1=>1 <2=>2 <3=>3 <4=>4 <5=>5 <6=>6 <7=>7 +#define RTE_I2C1_DMA_TX_EN 1 +#define RTE_I2C1_DMA_TX_REQID DMA_REQUEST_I2C1_TX +// Rx +// Channel <0=>0 <1=>1 <2=>2 <3=>3 <4=>4 <5=>5 <6=>6 <7=>7 +#define RTE_I2C1_DMA_RX_EN 1 +#define RTE_I2C1_DMA_RX_REQID DMA_REQUEST_I2C1_RX + + +// UART0 (Universal asynchronous receiver transmitter) [Driver_USART0] +// Configuration settings for Driver_USART0 in component ::Drivers:USART +#define RTE_UART0_CTS_PIN_EN 0 +#define RTE_UART0_RTS_PIN_EN 0 + +// { PAD_PIN27}, // 0 : gpio12 / 3 : UART0 RTSn +// { PAD_PIN28}, // 0 : gpio13 / 3 : UART0 CTSn +// { PAD_PIN29}, // 0 : gpio14 / 3 : UART0 RXD +// { PAD_PIN30}, // 0 : gpio15 / 3 : UART0 TXD +#define RTE_UART0_RTS_BIT 27 +#define RTE_UART0_RTS_FUNC PAD_MUX_ALT3 + +#define RTE_UART0_CTS_BIT 28 +#define RTE_UART0_CTS_FUNC PAD_MUX_ALT3 + +#define RTE_UART0_RX_BIT 29 +#define RTE_UART0_RX_FUNC PAD_MUX_ALT3 + +#define RTE_UART0_TX_BIT 30 +#define RTE_UART0_TX_FUNC PAD_MUX_ALT3 + +// DMA +// Tx +// Channel <0=>0 <1=>1 <2=>2 <3=>3 <4=>4 <5=>5 <6=>6 <7=>7 +#define RTE_UART0_DMA_TX_REQID DMA_REQUEST_USART0_TX +// Rx +// Channel <0=>0 <1=>1 <2=>2 <3=>3 <4=>4 <5=>5 <6=>6 <7=>7 +#define RTE_UART0_DMA_RX_REQID DMA_REQUEST_USART0_RX + +// UART1 (Universal asynchronous receiver transmitter) [Driver_USART1] +// Configuration settings for Driver_USART1 in component ::Drivers:USART +#define RTE_UART1_CTS_PIN_EN 0 +#define RTE_UART1_RTS_PIN_EN 0 + +// { PAD_PIN31}, // 0 : gpio16 / 1 : UART1 RTS +// { PAD_PIN32}, // 0 : gpio17 / 1 : UART1 CTS +// { PAD_PIN33}, // 0 : gpio18 / 1 : UART1 RXD +// { PAD_PIN34}, // 0 : gpio19 / 1 : UART1 TXD +#define RTE_UART1_RTS_BIT 31 +#define RTE_UART1_RTS_FUNC PAD_MUX_ALT1 + +#define RTE_UART1_CTS_BIT 32 +#define RTE_UART1_CTS_FUNC PAD_MUX_ALT1 + +#define RTE_UART1_RX_BIT 33 +#define RTE_UART1_RX_FUNC PAD_MUX_ALT1 + +#define RTE_UART1_TX_BIT 34 +#define RTE_UART1_TX_FUNC PAD_MUX_ALT1 + +// DMA +// Tx +// Channel <0=>0 <1=>1 <2=>2 <3=>3 <4=>4 <5=>5 <6=>6 <7=>7 +#define RTE_UART1_DMA_TX_REQID DMA_REQUEST_USART1_TX +// Rx +// Channel <0=>0 <1=>1 <2=>2 <3=>3 <4=>4 <5=>5 <6=>6 <7=>7 +#define RTE_UART1_DMA_RX_REQID DMA_REQUEST_USART1_RX + +// UART2 (Universal asynchronous receiver transmitter) [Driver_USART2] +// Configuration settings for Driver_USART2 in component ::Drivers:USART +#define RTE_UART2_CTS_PIN_EN 0 +#define RTE_UART2_RTS_PIN_EN 0 + +// { PAD_PIN25}, // 0 : gpio10 / 3 : UART2 RXD +// { PAD_PIN26}, // 0 : gpio11 / 3 : UART2 TXD +#define RTE_UART2_RX_BIT 27 +#define RTE_UART2_RX_FUNC PAD_MUX_ALT5 + +#define RTE_UART2_TX_BIT 28 +#define RTE_UART2_TX_FUNC PAD_MUX_ALT5 + + +// DMA +// Tx +// Channel <0=>0 <1=>1 <2=>2 <3=>3 <4=>4 <5=>5 <6=>6 <7=>7 +#define RTE_UART2_DMA_TX_REQID DMA_REQUEST_USART2_TX +// Rx +// Channel <0=>0 <1=>1 <2=>2 <3=>3 <4=>4 <5=>5 <6=>6 <7=>7 +#define RTE_UART2_DMA_RX_REQID DMA_REQUEST_USART2_RX + +// SPI0 (Serial Peripheral Interface) [Driver_SPI0] +// Configuration settings for Driver_SPI0 in component ::Drivers:SPI +#define RTE_SPI0 1 + +// { PAD_PIN23}, // 0 : gpio8 / 1 : SPI0 SSn +// { PAD_PIN24}, // 0 : gpio9 / 1 : SPI0 MOSI +// { PAD_PIN25}, // 0 : gpio10 / 1 : SPI0 MISO +// { PAD_PIN26}, // 0 : gpio11 / 1 : SPI0 SCLK +#define RTE_SPI0_SSN_BIT 23 +#define RTE_SPI0_SSN_FUNC PAD_MUX_ALT1 + +#define RTE_SPI0_MOSI_BIT 24 +#define RTE_SPI0_MOSI_FUNC PAD_MUX_ALT1 + +#define RTE_SPI0_MISO_BIT 25 +#define RTE_SPI0_MISO_FUNC PAD_MUX_ALT1 + +#define RTE_SPI0_SCLK_BIT 26 +#define RTE_SPI0_SCLK_FUNC PAD_MUX_ALT1 + +#define RTE_SPI0_SSN_GPIO_INSTANCE 0 +#define RTE_SPI0_SSN_GPIO_INDEX 8 + +// DMA +// Tx +// Channel <0=>0 <1=>1 <2=>2 <3=>3 <4=>4 <5=>5 <6=>6 <7=>7 +#define RTE_SPI0_DMA_TX_REQID DMA_REQUEST_SPI0_TX + +// Rx +// Channel <0=>0 <1=>1 <2=>2 <3=>3 <4=>4 <5=>5 <6=>6 <7=>7 +#define RTE_SPI0_DMA_RX_REQID DMA_REQUEST_SPI0_RX + +// SPI1 (Serial Peripheral Interface) [Driver_SPI1] +// Configuration settings for Driver_SPI1 in component ::Drivers:SPI +#define RTE_SPI1 0 + +// { PAD_PIN27}, // 0 : gpio12 / 1 : SPI1 SSn +// { PAD_PIN28}, // 0 : gpio13 / 1 : SPI1 MOSI +// { PAD_PIN29}, // 0 : gpio14 / 1 : SPI1 MISO +// { PAD_PIN30}, // 0 : gpio15 / 1 : SPI1 SCLK +// { PAD_PIN31}, // 0 : gpio16 / 4 : SPI1 SSn1 +#define RTE_SPI1_SSN_BIT 27 +#define RTE_SPI1_SSN_FUNC PAD_MUX_ALT1 + +#define RTE_SPI1_MOSI_BIT 28 +#define RTE_SPI1_MOSI_FUNC PAD_MUX_ALT1 + +#define RTE_SPI1_MISO_BIT 29 +#define RTE_SPI1_MISO_FUNC PAD_MUX_ALT1 + +#define RTE_SPI1_SCLK_BIT 30 +#define RTE_SPI1_SCLK_FUNC PAD_MUX_ALT1 + +#define RTE_SPI1_SSN_GPIO_INSTANCE 0 +#define RTE_SPI1_SSN_GPIO_INDEX 12 + +#define RTE_SPI1_SSN1_BIT 31 +#define RTE_SPI1_SSN1_FUNC PAD_MUX_ALT4 + +// DMA +// Tx +// Channel <0=>0 <1=>1 <2=>2 <3=>3 <4=>4 <5=>5 <6=>6 <7=>7 +#define RTE_SPI1_DMA_TX_REQID DMA_REQUEST_SPI1_TX + +// Rx +// Channel <0=>0 <1=>1 <2=>2 <3=>3 <4=>4 <5=>5 <6=>6 <7=>7 +#define RTE_SPI1_DMA_RX_REQID DMA_REQUEST_SPI1_RX + + +// PWM0 Controller [Driver_PWM0] +// Configuration settings for Driver_PWM0 in component ::Drivers:PWM +#define RTE_PWM 1 + +#define EFUSE_INIT_MODE POLLING_MODE +#define L2CTLS_INIT_MODE POLLING_MODE + +#define FLASH_BARE_RW_MODE 1 + + + + + +#define RTE_UART0 1 +#define RTE_UART1 1 +#define RTE_UART2 1 +/* to enable external thermal */ +#define EXTERNAL_NTC_EXIST 0 + + +#if (RTE_UART1 == 1) +#define UART1_DTR_PAD_INDEX 26 // GPIO11 +#define UART1_DTR_GPIO_INSTANCE 0 +#define UART1_DTR_GPIO_PIN 11 + +#define UART1_RI_PAD_INDEX 44 // AONIO 4 = GPIO24 +#define UART1_RI_GPIO_INSTANCE 1 +#define UART1_RI_GPIO_PIN 8 +#define UART1_RI_PWM_INSTANCE 1 +#define UART1_RI_PWM_CLK_ID FCLK_TIMER1 +#define UART1_RI_PWM_CLK_SEL FCLK_TIMER1_SEL_26M + +#define UART1_DCD_PAD_INDEX 45 // AONIO 5 = GPIO25 +#define UART1_DCD_GPIO_INSTANCE 1 +#define UART1_DCD_GPIO_PIN 9 +#endif + +#if (RTE_UART2 == 1) +#define UART2_DTR_PAD_INDEX 25 // GPIO10 +#define UART2_DTR_GPIO_INSTANCE 0 +#define UART2_DTR_GPIO_PIN 10 + +#define UART2_RI_PAD_INDEX 43 // AONIO 3 = GPIO23 +#define UART2_RI_GPIO_INSTANCE 1 +#define UART2_RI_GPIO_PIN 7 +#define UART2_RI_PWM_INSTANCE 0 +#define UART2_RI_PWM_CLK_ID FCLK_TIMER0 +#define UART2_RI_PWM_CLK_SEL FCLK_TIMER0_SEL_26M + +#define UART2_DCD_PAD_INDEX 47 // AONIO 7 = GPIO27 +#define UART2_DCD_GPIO_INSTANCE 1 +#define UART2_DCD_GPIO_PIN 11 +#endif + + +#define NETLIGHT_PAD_INDEX 46 // AONIO 6 = GPIO26 +#define NETLIGHT_PAD_ALT_FUNC PAD_MUX_ALT5 +#define NETLIGHT_PWM_INSTANCE 3 + +//USIM1 OPTION1 +#define USIM1_URST_OP1_PAD_INDEX 19 // GPIO4 +#define USIM1_URST_OP1_GPIO_INSTANCE 0 +#define USIM1_URST_OP1_GPIO_PIN 4 +#define USIM1_UCLK_OP1_PAD_INDEX 20 // GPIO5 +#define USIM1_UCLK_OP1_GPIO_INSTANCE 0 +#define USIM1_UCLK_OP1_GPIO_PIN 5 +#define USIM1_UIO_OP1_PAD_INDEX 21 // GPIO6 +#define USIM1_UIO_OP1_GPIO_INSTANCE 0 +#define USIM1_UIO_OP1_GPIO_PIN 6 + +//USIM1 OPTION2 +#define USIM1_UIO_OP2_PAD_INDEX 27 // GPIO12 +#define USIM1_UIO_OP2_GPIO_INSTANCE 0 +#define USIM1_UIO_OP2_GPIO_PIN 12 +#define USIM1_URST_OP2_PAD_INDEX 28 // GPIO13 +#define USIM1_URST_OP2_GPIO_INSTANCE 0 +#define USIM1_URST_OP2_GPIO_PIN 13 +#define USIM1_UCLK_OP2_PAD_INDEX 29 // GPIO14 +#define USIM1_UCLK_OP2_GPIO_INSTANCE 0 +#define USIM1_UCLK_OP2_GPIO_PIN 14 + +//USIM1 clock latched by AONIO, for example, use AONIO-6 test on EVB +#define AONIO_6_PAD_INDEX 46 // AONIO 6 = GPIO26 +#define AONIO_6_GPIO_INSTANCE 1 +#define AONIO_6_GPIO_PIN 10 + +#define RTE_CSPI0 0 + +#define RTE_CSPI0_MCLK_PAD_ADDR 39 +#define RTE_CSPI0_MCLK_FUNC PAD_MUX_ALT1 + +#define RTE_CSPI0_PCLK_PAD_ADDR 35 +#define RTE_CSPI0_PCLK_FUNC PAD_MUX_ALT1 + +#define RTE_CSPI0_CS_PAD_ADDR 36 +#define RTE_CSPI0_CS_FUNC PAD_MUX_ALT1 + +#define RTE_CSPI0_SDO0_PAD_ADDR 37 +#define RTE_CSPI0_SDO0_FUNC PAD_MUX_ALT1 + +#define RTE_CSPI0_SDO1_PAD_ADDR 38 +#define RTE_CSPI0_SDO1_FUNC PAD_MUX_ALT1 + +// DMA CSPI0 Request ID +#define RTE_CSPI0_DMA_RX_REQID DMA_REQUEST_I2S0_RX + +// CSPI1 Configuration +#define RTE_CSPI1 1 + +#define RTE_CSPI1_MCLK_PAD_ADDR 18 +#define RTE_CSPI1_MCLK_FUNC PAD_MUX_ALT1 + +#define RTE_CSPI1_PCLK_PAD_ADDR 19 +#define RTE_CSPI1_PCLK_FUNC PAD_MUX_ALT1 + +#define RTE_CSPI1_CS_PAD_ADDR 20 +#define RTE_CSPI1_CS_FUNC PAD_MUX_ALT1 + +#define RTE_CSPI1_SDO0_PAD_ADDR 21 +#define RTE_CSPI1_SDO0_FUNC PAD_MUX_ALT1 + +#define RTE_CSPI1_SDO1_PAD_ADDR 22 +#define RTE_CSPI1_SDO1_FUNC PAD_MUX_ALT1 + +// DMA CSPI1 Request ID +#define RTE_CSPI1_DMA_RX_REQID DMA_REQUEST_I2S1_RX + +#endif /* __RTE_DEVICE_H */ diff --git a/project/example_luatos_ftp/src/example_main.c b/project/example_luatos_ftp/src/example_main.c new file mode 100644 index 00000000..da873b99 --- /dev/null +++ b/project/example_luatos_ftp/src/example_main.c @@ -0,0 +1,130 @@ +#include "common_api.h" +#include "luat_rtos.h" +#include "luat_gpio.h" +#include "luat_debug.h" +#include "luat_mobile.h" +#include "luat_network_adapter.h" +#include "networkmgr.h" +#include "luat_ftp.h" + +#define FTP_OTA_TEST 1 + +static luat_rtos_task_handle luatos_http_task_handle; + +static void luatos_mobile_event_callback(LUAT_MOBILE_EVENT_E event, uint8_t index, uint8_t status) +{ + if (LUAT_MOBILE_EVENT_NETIF == event) + { + if (LUAT_MOBILE_NETIF_LINK_ON == status) + { + luat_socket_check_ready(index, NULL); + } + } +} + +static void luat_ftp_cb(luat_ftp_ctrl_t *luat_ftp_ctrl, FTP_SUCCESS_STATE_e event){ + LUAT_DEBUG_PRINT("%d", event); + char *data = NULL; + if(event == FTP_SUCCESS_DATA) + { + data = malloc(luat_ftp_ctrl->result_buffer.Pos + 1); + memcpy(data, luat_ftp_ctrl->result_buffer.Data, luat_ftp_ctrl->result_buffer.Pos + 1); + } + luat_rtos_event_send(luatos_http_task_handle, event, data, NULL, NULL, 0); +} + + +static uint8_t ftpclient_recv_response(luat_rtos_task_handle handle, luat_event_t event) +{ + luat_rtos_event_recv(luatos_http_task_handle, 0, &event, NULL, 0); + if(FTP_SUCCESS_DATA == event.id) + { + free(event.param1); + } + LUAT_DEBUG_PRINT("event id: %d", event.id); + return event.id; +} + +static void luatos_http_task(void *param) +{ + while (luat_mobile_get_register_status()!=1) + { + luat_rtos_task_sleep(500); + LUAT_DEBUG_PRINT("等待网络注册"); + } + luat_event_t event; +#if FTP_OTA_TEST == 1 + uint8_t ota_result = 0; +#endif + int result = luat_ftp_login(NW_ADAPTER_INDEX_LWIP_GPRS,"121.43.224.154", 21, "ftp_user", "3QujbiMG", NULL, luat_ftp_cb); + if(result) + { + luat_ftp_release(); + while (1) + { + LUAT_DEBUG_PRINT("ftp login fail"); + } + } + ftpclient_recv_response(luatos_http_task_handle, event); + + if(luat_ftp_command("LIST") == 0) + { + ftpclient_recv_response(luatos_http_task_handle, event); + } + + if(luat_ftp_pull("123123.txt", "/1234567.txt", 0) == 0) + { + ftpclient_recv_response(luatos_http_task_handle, event); + } + +#if FTP_OTA_TEST == 1 + if(luat_ftp_pull(NULL, "/ota_test.bin", 1) == 0) + { + ota_result = ftpclient_recv_response(luatos_http_task_handle, event); + } +#endif + if(luat_ftp_close() == 0) + { + ftpclient_recv_response(luatos_http_task_handle, event); + } + +#if FTP_OTA_TEST == 1 + if (FTP_SUCCESS_NO_DATA == ota_result) + { + luat_pm_reboot(); + } +#endif + while (1) + { + LUAT_DEBUG_PRINT("end"); + luat_rtos_task_sleep(5000); + } + // luat_ftp_command("NOOP"); + // luat_rtos_task_sleep(5000); + // luat_ftp_command("SYST"); + // luat_rtos_task_sleep(5000); + // luat_ftp_command("TYPE I"); + // luat_rtos_task_sleep(5000); + // luat_ftp_command("PWD"); + // luat_rtos_task_sleep(5000); + // luat_ftp_command("MKD QWER"); + // luat_rtos_task_sleep(5000); + // luat_ftp_command("CWD /QWER"); + // luat_rtos_task_sleep(5000); + // luat_ftp_command("CDUP"); + // luat_rtos_task_sleep(5000); + // luat_ftp_command("RMD QWER"); +} + + + +static void luat_test_init(void) +{ + luat_mobile_event_register_handler(luatos_mobile_event_callback); + net_lwip_init(); + net_lwip_register_adapter(NW_ADAPTER_INDEX_LWIP_GPRS); + network_register_set_default(NW_ADAPTER_INDEX_LWIP_GPRS); + luat_rtos_task_create(&luatos_http_task_handle, 4 * 1024, 50, "test", luatos_http_task, NULL, 16); + +} +INIT_TASK_EXPORT(luat_test_init, "1"); diff --git a/project/example_luatos_ftp/xmake.lua b/project/example_luatos_ftp/xmake.lua new file mode 100644 index 00000000..afca45d4 --- /dev/null +++ b/project/example_luatos_ftp/xmake.lua @@ -0,0 +1,23 @@ +local TARGET_NAME = "example_ftp" +local LIB_DIR = "$(buildir)/".. TARGET_NAME .. "/" +local LIB_NAME = "lib" .. TARGET_NAME .. ".a " +includes(SDK_TOP.."/thirdparty/libftp") +includes(SDK_TOP.."/luatos_lwip_socket") +target(TARGET_NAME) + set_kind("static") + set_targetdir(LIB_DIR) + add_deps("libftp") + + --加入代码和头文件 + add_includedirs("./inc",{public = true}) + add_files("./src/*.c",{public = true}) + + --路径可以随便写,可以加任意路径的代码,下面代码等效上方代码 + -- add_includedirs(SDK_TOP .. "project/" .. TARGET_NAME .. "/inc",{public = true}) + -- add_files(SDK_TOP .. "project/" .. TARGET_NAME .. "/src/*.c",{public = true}) + + --可以继续增加add_includedirs和add_files + --自动链接 + LIB_USER = LIB_USER .. SDK_TOP .. LIB_DIR .. LIB_NAME .. " " + --甚至可以加入自己的库 +target_end() \ No newline at end of file diff --git a/thirdparty/libftp/luat_ftp.h b/thirdparty/libftp/luat_ftp.h new file mode 100644 index 00000000..53d01dcf --- /dev/null +++ b/thirdparty/libftp/luat_ftp.h @@ -0,0 +1,123 @@ +#ifndef LUAT_FTP_H +#define LUAT_FTP_H + +#include "luat_fota.h" + +#define FTP_CMD_SEND_MAX (128) +#define FTP_CMD_RECV_MAX (1024) +#define PUSH_BUFF_SIZE (4096) +#define FTP_SOCKET_TIMEOUT (30000) + +#define FTP_OK (0) +#define FTP_ERROR_STATE (-1) +#define FTP_ERROR_HEADER (-2) +#define FTP_ERROR_BODY (-3) +#define FTP_ERROR_CONNECT (-4) +#define FTP_ERROR_CLOSE (-5) +#define FTP_ERROR_RX (-6) +#define FTP_ERROR_DOWNLOAD (-7) +#define FTP_ERROR_FILE (-8) +#define FTP_ERROR_NO_MEM (-9) +#define FTP_ERROR_NETWORK (-10) +#define FTP_RX_TIMEOUT (-6) + +#define FTP_RESTART_MARKER "110" //Restart marker reply. +#define FTP_SERVICE_MIN_OK "120" //Service ready in nnn minutes. +#define FTP_DATA_CON_OPEN "125" //Data connection already open; transfer starting. +#define FTP_FILE_STATUS_OK "150" //File status okay; about to open data connection. +#define FTP_COMMAND_OK "200" //Command okay. +#define FTP_COM_NOT_IMP "202" //Command not implemented, superfluous at this site. +#define FTP_SYSTEM_STATUS "211" //System status, or system help reply. +#define FTP_DIRECTORY_STATUS "212" //Directory status. +#define FTP_FILE_STATUS "213" //File status. +#define FTP_HELP_MESSAGE "214" //Help message. +#define FTP_SYSTEM_TYPE "215" //NAME system type. +#define FTP_SERVICE_NEW_OK "220" //Service ready for new user. +#define FTP_CLOSE_CONTROL "221" //Service closing control connection. +#define FTP_CLOSE_CONNECT "226" //Closing data connection. +#define FTP_ENTER_PASSIVE "227" //Entering Passive Mode (h1,h2,h3,h4,p1,p2). +#define FTP_LOGIN_OK "230" //User logged in, proceed. +#define FTP_FILE_REQUESTED_OK "250" //Requested file action okay, completed. +#define FTP_PATHNAME_OK "257" //"PATHNAME" created. +#define FTP_USERNAME_OK "331" //User name okay, need password. +#define FTP_DATA_CON_FAIL "425" //Can't open data connection. + +typedef enum{ + FTP_ERROR , + FTP_SUCCESS_NO_DATA , + FTP_SUCCESS_DATA , +}FTP_SUCCESS_STATE_e; + +enum{ + FTP_COMMAND_SYST = 1, + FTP_COMMAND_PULL , + FTP_COMMAND_PUSH , + FTP_COMMAND_CLOSE , +}; + +enum{ + FTP_REQ_LOGIN = 1 , + FTP_REQ_COMMAND , + FTP_REQ_PULL , + FTP_REQ_PUSH , + FTP_REQ_CLOSE , + + FTP_EVENT_LOGIN = USER_EVENT_ID_START + FTP_REQ_LOGIN, + FTP_EVENT_COMMAND , + FTP_EVENT_PULL , + FTP_EVENT_PUSH , + FTP_EVENT_CLOSE , + FTP_EVENT_DATA_CONNECT , + FTP_EVENT_DATA_TX_DONE , + FTP_EVENT_DATA_WRITE_FILE , + FTP_EVENT_DATA_CLOSED , +}; + +typedef struct{ + network_ctrl_t *cmd_netc; // ftp netc + network_ctrl_t *data_netc; // ftp data_netc + luat_ip_addr_t ip_addr; // ftp ip + char addr[64]; // ftp addr + char username[64]; // ftp username + char password[64]; // ftp password + char remote_name[64];//去掉? + size_t upload_done_size; + size_t local_file_size; + uint8_t cmd_send_data[FTP_CMD_SEND_MAX]; + uint32_t cmd_send_len; + uint8_t cmd_recv_data[FTP_CMD_RECV_MAX]; + uint32_t cmd_recv_len; + uint16_t port; // 端口号 + uint8_t adapter_index; + uint8_t data_netc_online; + uint8_t data_netc_connecting; + void* ftp_cb; /**< mqtt 回调函数*/ +}luat_ftp_network_t; + +typedef struct{ + luat_rtos_task_handle task_handle; + luat_ftp_network_t *network; + FILE* fd; //下载 FILE + Buffer_Struct result_buffer; + uint8_t is_run; + uint8_t is_fota; + luat_fota_img_proc_ctx_ptr context; +}luat_ftp_ctrl_t; + +typedef struct{ + char *server_cert; + char *client_cert; + char *client_key; + char *client_password; +}luat_ftp_tls_t; + +typedef void (*luat_ftp_cb_t)(luat_ftp_ctrl_t *luat_ftp_ctrl, FTP_SUCCESS_STATE_e event); + +uint32_t luat_ftp_release(void); +int luat_ftp_close(void); +int luat_ftp_login(uint8_t adapter,const char * ip_addr,uint16_t port,const char * username,const char * password,luat_ftp_tls_t* luat_ftp_tls,luat_ftp_cb_t ftp_cb); +int luat_ftp_command(const char * command); +int luat_ftp_pull(const char * local_name, const char * remote_name, uint8_t is_fota); +int luat_ftp_push(const char * local_name, const char * remote_name); + +#endif diff --git a/thirdparty/libftp/luat_ftp_client.c b/thirdparty/libftp/luat_ftp_client.c new file mode 100644 index 00000000..3b39c9c8 --- /dev/null +++ b/thirdparty/libftp/luat_ftp_client.c @@ -0,0 +1,850 @@ +/* +@module ftp +@summary ftp 客户端 +@version 1.0 +@date 2022.09.05 +@demo ftp +@tag LUAT_USE_FTP +*/ + +#include "luat_network_adapter.h" +#include "luat_rtos.h" +#include "luat_fs.h" +#include "luat_mem.h" + +#include "luat_ftp.h" +#include "luat_debug.h" + + +#define FTP_DEBUG 0 +#if FTP_DEBUG == 0 +#undef LUAT_DEBUG_PRINT +#define LUAT_DEBUG_PRINT(...) +#endif + +luat_ftp_ctrl_t g_s_ftp; + +uint32_t luat_ftp_release(void) { + if (!g_s_ftp.network) return 0; + if (g_s_ftp.network->cmd_netc){ + network_force_close_socket(g_s_ftp.network->cmd_netc); + network_release_ctrl(g_s_ftp.network->cmd_netc); + g_s_ftp.network->cmd_netc = NULL; + } + if (g_s_ftp.network->data_netc){ + network_force_close_socket(g_s_ftp.network->data_netc); + network_release_ctrl(g_s_ftp.network->data_netc); + g_s_ftp.network->data_netc = NULL; + } + luat_heap_free(g_s_ftp.network); + g_s_ftp.network = NULL; + return 0; +} + +static uint32_t luat_ftp_data_send(luat_ftp_ctrl_t *ftp_ctrl, uint8_t* send_data, uint32_t send_len) { + if (send_len == 0) + return 0; + uint32_t tx_len = 0; + LUAT_DEBUG_PRINT("luat_ftp_data_send data:%d",send_len); + network_tx(g_s_ftp.network->data_netc, send_data, send_len, 0, NULL, 0, &tx_len, 0); + return tx_len; +} + +static uint32_t luat_ftp_cmd_send(luat_ftp_ctrl_t *ftp_ctrl, uint8_t* send_data, uint32_t send_len,uint32_t timeout_ms) { + if (send_len == 0) + return 0; + uint32_t tx_len = 0; + LUAT_DEBUG_PRINT("luat_ftp_cmd_send data:%.*s",send_len,send_data); + network_tx(g_s_ftp.network->cmd_netc, send_data, send_len, 0, NULL, 0, &tx_len, timeout_ms); + return tx_len; +} + +static int luat_ftp_cmd_recv(luat_ftp_ctrl_t *ftp_ctrl,uint8_t *recv_data,uint32_t *recv_len,uint32_t timeout_ms){ + uint32_t total_len = 0; + uint8_t is_break = 0,is_timeout = 0; + int ret = network_wait_rx(g_s_ftp.network->cmd_netc, timeout_ms, &is_break, &is_timeout); + LUAT_DEBUG_PRINT("network_wait_rx ret:%d is_break:%d is_timeout:%d",ret,is_break,is_timeout); + if (ret) + return -1; + if (is_timeout) + return 1; + else if (is_break) + return 2; + int result = network_rx(g_s_ftp.network->cmd_netc, NULL, 0, 0, NULL, NULL, &total_len); + if (0 == result){ + if (total_len>0){ +next: + result = network_rx(g_s_ftp.network->cmd_netc, recv_data, total_len, 0, NULL, NULL, recv_len); + LUAT_DEBUG_PRINT("result:%d recv_len:%d",result,*recv_len); + LUAT_DEBUG_PRINT("recv_data %.*s",total_len, recv_data); + if (result) + goto next; + if (*recv_len == 0||result!=0) { + return -1; + } + return 0; + } + }else{ + LUAT_DEBUG_PRINT("ftp network_rx fail"); + return -1; + } + return 0; +} + +static int32_t luat_ftp_data_callback(void *data, void *param){ + OS_EVENT *event = (OS_EVENT *)data; + uint8_t *rx_buffer; + int ret = 0; + uint32_t rx_len = 0; + if (!g_s_ftp.network) + { + return 0; + } + LUAT_DEBUG_PRINT("event->ID %d LINK %d ON_LINE %d EVENT %d TX_OK %d CLOSED %d",event->ID,EV_NW_RESULT_LINK & 0x0fffffff,EV_NW_RESULT_CONNECT & 0x0fffffff,EV_NW_RESULT_EVENT & 0x0fffffff,EV_NW_RESULT_TX & 0x0fffffff,EV_NW_RESULT_CLOSE & 0x0fffffff); + LUAT_DEBUG_PRINT("luat_ftp_data_callback %d %d",event->ID - EV_NW_RESULT_BASE, event->Param1); + if (event->Param1){ + if (EV_NW_RESULT_CONNECT == event->ID) + { + luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_DATA_CONNECT, 0xffffffff, 0, 0, LUAT_WAIT_FOREVER); + } + else + { + luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_DATA_CLOSED, 0, 0, 0, LUAT_WAIT_FOREVER); + } + return -1; + } + switch (event->ID) + { + case EV_NW_RESULT_TX: + luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_DATA_TX_DONE, 0, 0, 0, LUAT_WAIT_FOREVER); + break; + case EV_NW_RESULT_EVENT: + rx_buffer = NULL; + uint8_t tmpbuff[4]; + do + { + // 先读取长度 + ret = network_rx(g_s_ftp.network->data_netc, NULL, 0, 0, NULL, NULL, &rx_len); + if (rx_len <= 0) { + // 没数据? 那也读一次, 然后退出 + network_rx(g_s_ftp.network->data_netc, tmpbuff, 4, 0, NULL, NULL, &rx_len); + break; + } + if (rx_len > 2048) + rx_len = 2048; + rx_buffer = luat_heap_malloc(rx_len); + // 如果rx_buffer == NULL, 内存炸了 + if (rx_buffer == NULL) { + LUAT_DEBUG_PRINT("out of memory when malloc ftp buff"); + network_close(g_s_ftp.network->data_netc, 0); + return -1; + } + ret = network_rx(g_s_ftp.network->data_netc, rx_buffer, rx_len, 0, NULL, NULL, &rx_len); + LUAT_DEBUG_PRINT("luat_ftp_data_callback network_rx ret:%d rx_len:%d",ret,rx_len); + if (!ret && rx_len > 0) + { + if (g_s_ftp.fd || g_s_ftp.is_fota == 1) + { + luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_DATA_WRITE_FILE, rx_buffer, rx_len, 0, LUAT_WAIT_FOREVER); + rx_buffer = NULL; + continue; + } + else + { + OS_BufferWrite(&g_s_ftp.result_buffer, rx_buffer, rx_len); + } + } + luat_heap_free(rx_buffer); + rx_buffer = NULL; + } while (!ret && rx_len); + if (rx_buffer) + luat_heap_free(rx_buffer); + rx_buffer = NULL; + break; + case EV_NW_RESULT_CLOSE: + luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_DATA_CLOSED, 0, 0, 0, LUAT_WAIT_FOREVER); + return 0; + break; + case EV_NW_RESULT_CONNECT: + luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_DATA_CONNECT, 0, 0, 0, LUAT_WAIT_FOREVER); + break; + case EV_NW_RESULT_LINK: + return 0; + } + + ret = network_wait_event(g_s_ftp.network->data_netc, NULL, 0, NULL); + if (ret < 0){ + network_close(g_s_ftp.network->data_netc, 0); + return -1; + } + return 0; +} + +static int32_t ftp_task_cb(void *pdata, void *param) +{ + OS_EVENT *event = pdata; + if (event->ID >= FTP_EVENT_LOGIN && event->ID <= FTP_EVENT_PUSH) + { + LUAT_DEBUG_PRINT("last cmd not finish, ignore %d,%u,%u,%x", event->ID - USER_EVENT_ID_START, event->Param1, event->Param2, param); + return -1; + } + switch(event->ID) + { + case FTP_EVENT_DATA_WRITE_FILE: + if (g_s_ftp.is_fota) + { + luat_fota_write(g_s_ftp.context, (void*)event->Param1, event->Param2); + luat_heap_free((void*)event->Param1); + }else if (g_s_ftp.fd){ + luat_fs_fwrite((void*)event->Param1, event->Param2, 1, g_s_ftp.fd); + luat_heap_free((void*)event->Param1); + } + break; + case FTP_EVENT_DATA_TX_DONE: + g_s_ftp.network->upload_done_size = (size_t)g_s_ftp.network->data_netc->ack_size; + if (g_s_ftp.network->upload_done_size >= g_s_ftp.network->local_file_size) + { + LUAT_DEBUG_PRINT("ftp data upload done!"); + network_close(g_s_ftp.network->data_netc, 0); + } + break; + case FTP_EVENT_DATA_CONNECT: + if (g_s_ftp.network->data_netc_connecting) + { + g_s_ftp.network->data_netc_connecting = 0; + g_s_ftp.network->data_netc_online = !event->Param1; + } + break; + case FTP_EVENT_DATA_CLOSED: + LUAT_DEBUG_PRINT("ftp data channel close"); + g_s_ftp.network->data_netc_online = 0; + if (g_s_ftp.network->data_netc) + { + network_force_close_socket(g_s_ftp.network->data_netc); + network_release_ctrl(g_s_ftp.network->data_netc); + g_s_ftp.network->data_netc = NULL; + } + break; + case FTP_EVENT_CLOSE: + g_s_ftp.is_run = 0; + break; + default: +// LUAT_DEBUG_PRINT("ignore %x,%x,%x", event->ID, param, EV_NW_RESULT_EVENT); + break; + } + return 0; +} + +static int luat_ftp_pasv_connect(luat_ftp_ctrl_t *ftp_ctrl,uint32_t timeout_ms){ + char h1[4]={0},h2[4]={0},h3[4]={0},h4[4]={0},p1[4]={0},p2[4]={0},data_addr[64]={0}; + uint8_t port1,port2; + uint16_t data_port; + luat_ftp_cmd_send(&g_s_ftp, (uint8_t*)"PASV\r\n", strlen("PASV\r\n"),FTP_SOCKET_TIMEOUT); + int ret = luat_ftp_cmd_recv(&g_s_ftp,g_s_ftp.network->cmd_recv_data,&g_s_ftp.network->cmd_recv_len,FTP_SOCKET_TIMEOUT); + if (ret){ + return -1; + }else{ + LUAT_DEBUG_PRINT("luat_ftp_pasv_connect cmd_recv_data",g_s_ftp.network->cmd_recv_data); + if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_ENTER_PASSIVE, 3)){ + LUAT_DEBUG_PRINT("ftp pasv_connect wrong"); + return -1; + } + } + char *temp = memchr(g_s_ftp.network->cmd_recv_data, '(', strlen((const char *)(g_s_ftp.network->cmd_recv_data))); + char *temp1 = memchr(temp+1, ',', strlen(temp)-1); + memcpy(h1, temp+1, temp1-temp-1); + char *temp2 = memchr(temp1+1, ',', strlen(temp1)-1); + memcpy(h2, temp1+1, temp2-temp1-1); + char *temp3 = memchr(temp2+1, ',', strlen(temp2)-1); + memcpy(h3, temp2+1, temp3-temp2-1); + char *temp4 = memchr(temp3+1, ',', strlen(temp3)-1); + memcpy(h4, temp3+1, temp4-temp3-1); + char *temp5 = memchr(temp4+1, ',', strlen(temp4)-1); + memcpy(p1, temp4+1, temp5-temp4-1); + char *temp6 = memchr(temp5+1, ')', strlen(temp5)-1); + memcpy(p2, temp5+1, temp6-temp5-1); + snprintf_(data_addr, 64, "%s.%s.%s.%s",h1,h2,h3,h4); + port1 = (uint8_t)atoi(p1); + port2 = (uint8_t)atoi(p2); + data_port = port1 * 256 + port2; + LUAT_DEBUG_PRINT("data_addr:%s data_port:%d",data_addr,data_port); + if (memcmp(data_addr,"172.",4)==0||memcmp(data_addr,"192.",4)==0||memcmp(data_addr,"10.",3)==0||memcmp(data_addr,"127.0.0.1",9)==0||memcmp(data_addr,"169.254.0.0",11)==0||memcmp(data_addr,"169.254.0.16",12)==0){ + memset(data_addr,0,64); + LUAT_DEBUG_PRINT("g_s_ftp.network->addr:%s",g_s_ftp.network->addr); + memcpy(data_addr, g_s_ftp.network->addr, strlen(g_s_ftp.network->addr)+1); + } + LUAT_DEBUG_PRINT("data_addr:%s data_port:%d",data_addr,data_port); + if (g_s_ftp.network->data_netc) + { + LUAT_DEBUG_PRINT("data_netc already create"); + return -1; + } + g_s_ftp.network->data_netc = network_alloc_ctrl(g_s_ftp.network->adapter_index); + if (!g_s_ftp.network->data_netc){ + LUAT_DEBUG_PRINT("data_netc create fail"); + return -1; + } + network_init_ctrl(g_s_ftp.network->data_netc,NULL, luat_ftp_data_callback, g_s_ftp.network); + network_set_base_mode(g_s_ftp.network->data_netc, 1, 10000, 0, 0, 0, 0); + network_set_local_port(g_s_ftp.network->data_netc, 0); + network_deinit_tls(g_s_ftp.network->data_netc); + if(network_connect(g_s_ftp.network->data_netc, data_addr, strlen(data_addr), NULL, data_port, 0)<0){ + LUAT_DEBUG_PRINT("ftp data network connect fail"); + network_force_close_socket(g_s_ftp.network->data_netc); + network_release_ctrl(g_s_ftp.network->data_netc); + g_s_ftp.network->data_netc = NULL; + return -1; + } + uint8_t is_timeout; + OS_EVENT event; + g_s_ftp.network->data_netc_connecting = 1; + g_s_ftp.network->data_netc_online = 0; + while(g_s_ftp.network->data_netc_connecting) + { + if (network_wait_event(g_s_ftp.network->cmd_netc, &event, timeout_ms, &is_timeout)) + { + return -1; + } + if (is_timeout) + { + return -1; + } + if (event.ID) + { + ftp_task_cb(&event, NULL); + } + else + { + if (g_s_ftp.network->cmd_netc->new_rx_flag) + { + network_rx(g_s_ftp.network->cmd_netc, g_s_ftp.network->cmd_recv_data, 1024, 0, NULL, NULL, &g_s_ftp.network->cmd_recv_len); + LUAT_DEBUG_PRINT("ftp cmd rx %.*s", g_s_ftp.network->cmd_recv_len, g_s_ftp.network->cmd_recv_data); + } + } + } + if (g_s_ftp.network->data_netc_online) + { + LUAT_DEBUG_PRINT("ftp pasv_connect ok"); + return 0; + } + return -1; +} + + + +static int ftp_login(void) +{ + int ret; + if(network_connect(g_s_ftp.network->cmd_netc, g_s_ftp.network->addr, strlen(g_s_ftp.network->addr), NULL, g_s_ftp.network->port, FTP_SOCKET_TIMEOUT)){ + LUAT_DEBUG_PRINT("ftp network_connect fail"); + return -1; + } + ret = luat_ftp_cmd_recv(&g_s_ftp,g_s_ftp.network->cmd_recv_data,&g_s_ftp.network->cmd_recv_len,FTP_SOCKET_TIMEOUT); + if (ret){ + return -1; + }else{ + if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_SERVICE_NEW_OK, 3)){ + LUAT_DEBUG_PRINT("ftp connect error"); + return -1; + } + } + LUAT_DEBUG_PRINT("ftp connect ok"); + memset(g_s_ftp.network->cmd_send_data,0,FTP_CMD_SEND_MAX); + snprintf_((char *)(g_s_ftp.network->cmd_send_data), FTP_CMD_SEND_MAX, "USER %s\r\n",g_s_ftp.network->username); + luat_ftp_cmd_send(&g_s_ftp, g_s_ftp.network->cmd_send_data, strlen((const char *)(g_s_ftp.network->cmd_send_data)),FTP_SOCKET_TIMEOUT); + ret = luat_ftp_cmd_recv(&g_s_ftp,g_s_ftp.network->cmd_recv_data,&g_s_ftp.network->cmd_recv_len,FTP_SOCKET_TIMEOUT); + if (ret){ + LUAT_DEBUG_PRINT("ftp username wrong"); + return -1; + }else{ + if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_USERNAME_OK, 3)){ + LUAT_DEBUG_PRINT("ftp username wrong"); + return -1; + } + } + LUAT_DEBUG_PRINT("ftp username ok"); + memset(g_s_ftp.network->cmd_send_data,0,FTP_CMD_SEND_MAX); + snprintf_((char *)(g_s_ftp.network->cmd_send_data), FTP_CMD_SEND_MAX, "PASS %s\r\n",g_s_ftp.network->password); + luat_ftp_cmd_send(&g_s_ftp, g_s_ftp.network->cmd_send_data, strlen((const char *)(g_s_ftp.network->cmd_send_data)),FTP_SOCKET_TIMEOUT); + ret = luat_ftp_cmd_recv(&g_s_ftp,g_s_ftp.network->cmd_recv_data,&g_s_ftp.network->cmd_recv_len,FTP_SOCKET_TIMEOUT); + if (ret){ + LUAT_DEBUG_PRINT("ftp login wrong"); + return -1; + }else{ + if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_LOGIN_OK, 3)){ + LUAT_DEBUG_PRINT("ftp login wrong"); + return -1; + } + } + LUAT_DEBUG_PRINT("ftp login ok"); + return 0; +} + +static void l_ftp_cb(FTP_SUCCESS_STATE_e state){ + if (g_s_ftp.network->ftp_cb){ + luat_ftp_cb_t ftp_cb = g_s_ftp.network->ftp_cb; + ftp_cb(&g_s_ftp,state); + } + OS_DeInitBuffer(&g_s_ftp.result_buffer); +} + +static void ftp_task(void *param){ + FTP_SUCCESS_STATE_e ftp_state = FTP_SUCCESS_NO_DATA; + int ret; + int count = 0; + luat_rtos_task_handle task_handle = g_s_ftp.task_handle; + OS_EVENT task_event; + uint8_t is_timeout = 0; + g_s_ftp.is_run = 1; + luat_rtos_event_recv(g_s_ftp.task_handle, FTP_EVENT_LOGIN, &task_event, NULL, LUAT_WAIT_FOREVER); + if (ftp_login()){ + LUAT_DEBUG_PRINT("ftp login fail"); + luat_ftp_release(); + ftp_state = FTP_ERROR; + l_ftp_cb(ftp_state); + g_s_ftp.task_handle = NULL; + luat_rtos_task_delete(task_handle); + return; + }else{ + l_ftp_cb(ftp_state); + } + while (g_s_ftp.is_run) { + is_timeout = 0; + ret = network_wait_event(g_s_ftp.network->cmd_netc, &task_event, 3600000, &is_timeout); + if (ret < 0){ + LUAT_DEBUG_PRINT("ftp network error"); + goto wait_event_and_out; + }else if (is_timeout || !task_event.ID){ + if (g_s_ftp.network->cmd_netc->new_rx_flag){ + network_rx(g_s_ftp.network->cmd_netc, g_s_ftp.network->cmd_recv_data, 1024, 0, NULL, NULL, &ret); + LUAT_DEBUG_PRINT("ftp rx %dbyte", ret); + } + continue; + } + ftp_state = FTP_SUCCESS_NO_DATA; + switch (task_event.ID) + { + case FTP_EVENT_LOGIN: + break; + case FTP_EVENT_PULL: + if (g_s_ftp.network->data_netc) + { + network_force_close_socket(g_s_ftp.network->data_netc); + network_release_ctrl(g_s_ftp.network->data_netc); + g_s_ftp.network->data_netc = NULL; + } + if(luat_ftp_pasv_connect(&g_s_ftp,FTP_SOCKET_TIMEOUT)){ + LUAT_DEBUG_PRINT("ftp pasv_connect fail"); + goto operation_failed; + } + snprintf_((char *)(g_s_ftp.network->cmd_send_data), FTP_CMD_SEND_MAX, "RETR %s\r\n",g_s_ftp.network->remote_name); + luat_ftp_cmd_send(&g_s_ftp, g_s_ftp.network->cmd_send_data, strlen((const char *)g_s_ftp.network->cmd_send_data),FTP_SOCKET_TIMEOUT); + ret = luat_ftp_cmd_recv(&g_s_ftp,g_s_ftp.network->cmd_recv_data,&g_s_ftp.network->cmd_recv_len,FTP_SOCKET_TIMEOUT); + if (ret){ + goto operation_failed; + }else{ + + if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_FILE_STATUS_OK, 3)){ + LUAT_DEBUG_PRINT("ftp RETR wrong"); + goto operation_failed; + } + } + if (!g_s_ftp.network->data_netc_online) + { + g_s_ftp.network->cmd_recv_data[g_s_ftp.network->cmd_recv_len] = 0; + LUAT_DEBUG_PRINT("ftp RETR maybe done!"); + if (strstr((const char *)(g_s_ftp.network->cmd_recv_data), "226 ")) + { + LUAT_DEBUG_PRINT("ftp RETR ok!"); + + if(g_s_ftp.is_fota) + { + if(luat_fota_done(g_s_ftp.context)){ + ftp_state = FTP_ERROR; + } + g_s_ftp.is_fota = 0; + } else if (g_s_ftp.fd){ + luat_fs_fclose(g_s_ftp.fd); + g_s_ftp.fd = NULL; + } + l_ftp_cb(ftp_state); + break; + } + } + ret = luat_ftp_cmd_recv(&g_s_ftp,g_s_ftp.network->cmd_recv_data,&g_s_ftp.network->cmd_recv_len,FTP_SOCKET_TIMEOUT); + if (ret){ + goto operation_failed; + }else{ + if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_CLOSE_CONNECT, 3)){ + LUAT_DEBUG_PRINT("ftp RETR wrong"); + goto operation_failed; + } + } + while (count<3 && g_s_ftp.network->data_netc_online!=0){ + luat_ftp_cmd_recv(&g_s_ftp,g_s_ftp.network->cmd_recv_data,&g_s_ftp.network->cmd_recv_len,FTP_SOCKET_TIMEOUT/3); + count++; + } + + if (g_s_ftp.is_fota){ + if(luat_fota_done(g_s_ftp.context)){ + ftp_state = FTP_ERROR; + } + g_s_ftp.is_fota = 0; + } else if (g_s_ftp.fd){ + luat_fs_fclose(g_s_ftp.fd); + g_s_ftp.fd = NULL; + } + l_ftp_cb(ftp_state); + break; + case FTP_EVENT_PUSH: + if(luat_ftp_pasv_connect(&g_s_ftp,FTP_SOCKET_TIMEOUT)){ + LUAT_DEBUG_PRINT("ftp pasv_connect fail"); + goto operation_failed; + } + + memset(g_s_ftp.network->cmd_send_data,0,FTP_CMD_SEND_MAX); + snprintf_((char *)(g_s_ftp.network->cmd_send_data), FTP_CMD_SEND_MAX, "STOR %s\r\n",g_s_ftp.network->remote_name); + luat_ftp_cmd_send(&g_s_ftp, g_s_ftp.network->cmd_send_data, strlen((const char *)g_s_ftp.network->cmd_send_data),FTP_SOCKET_TIMEOUT); + ret = luat_ftp_cmd_recv(&g_s_ftp,g_s_ftp.network->cmd_recv_data,&g_s_ftp.network->cmd_recv_len,FTP_SOCKET_TIMEOUT); + if (ret){ + goto operation_failed; + }else{ + if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_FILE_STATUS_OK, 3)){ + LUAT_DEBUG_PRINT("ftp STOR wrong"); + goto operation_failed; + } + } + + uint8_t* buff = luat_heap_malloc(PUSH_BUFF_SIZE); + int offset = 0; + g_s_ftp.network->upload_done_size = 0; + while (1) { + memset(buff, 0, PUSH_BUFF_SIZE); + int len = luat_fs_fread(buff, sizeof(uint8_t), PUSH_BUFF_SIZE, g_s_ftp.fd); + if (len < 1) + break; + luat_ftp_data_send(&g_s_ftp, buff, len); + offset += len; + } + luat_heap_free(buff); + LUAT_DEBUG_PRINT("offset:%d file_size:%d",offset,g_s_ftp.network->local_file_size); + ret = luat_ftp_cmd_recv(&g_s_ftp,g_s_ftp.network->cmd_recv_data,&g_s_ftp.network->cmd_recv_len,FTP_SOCKET_TIMEOUT); + if (g_s_ftp.network->upload_done_size != g_s_ftp.network->local_file_size) + { + LUAT_DEBUG_PRINT("upload not finish !!! %d,%d", g_s_ftp.network->upload_done_size, g_s_ftp.network->local_file_size); + } + if (ret){ + goto operation_failed; + }else{ + if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_CLOSE_CONNECT, 3)){ + LUAT_DEBUG_PRINT("ftp STOR wrong"); + } + } + while (count<3 && g_s_ftp.network->data_netc_online!=0){ + luat_ftp_cmd_recv(&g_s_ftp,g_s_ftp.network->cmd_recv_data,&g_s_ftp.network->cmd_recv_len,FTP_SOCKET_TIMEOUT/3); + count++; + } + if (g_s_ftp.fd){ + luat_fs_fclose(g_s_ftp.fd); + g_s_ftp.fd = NULL; + } + l_ftp_cb(ftp_state); + break; + case FTP_EVENT_CLOSE: + g_s_ftp.is_run = 0; + break; + case FTP_EVENT_COMMAND: + OS_DeInitBuffer(&g_s_ftp.result_buffer); + if(!memcmp(g_s_ftp.network->cmd_send_data, "LIST", 4)) + { + if(luat_ftp_pasv_connect(&g_s_ftp,FTP_SOCKET_TIMEOUT)){ + LUAT_DEBUG_PRINT("ftp pasv_connect fail"); + goto operation_failed; + } + luat_ftp_cmd_send(&g_s_ftp, g_s_ftp.network->cmd_send_data, strlen((const char *)(g_s_ftp.network->cmd_send_data)),FTP_SOCKET_TIMEOUT); + ret = luat_ftp_cmd_recv(&g_s_ftp,g_s_ftp.network->cmd_recv_data,&g_s_ftp.network->cmd_recv_len,FTP_SOCKET_TIMEOUT); + if (ret){ + goto operation_failed; + }else{ + if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_FILE_STATUS_OK, 3)){ + LUAT_DEBUG_PRINT("ftp LIST wrong"); + goto operation_failed; + } + } + if (!g_s_ftp.network->data_netc_online) + { + g_s_ftp.network->cmd_recv_data[g_s_ftp.network->cmd_recv_len] = 0; + LUAT_DEBUG_PRINT("ftp LIST maybe done!"); + if (strstr((const char *)(g_s_ftp.network->cmd_recv_data), FTP_CLOSE_CONNECT)) + { + LUAT_DEBUG_PRINT("ftp LIST ok!"); + ftp_state = FTP_SUCCESS_DATA; + l_ftp_cb(ftp_state); + break; + } + } + ret = luat_ftp_cmd_recv(&g_s_ftp,g_s_ftp.network->cmd_recv_data,&g_s_ftp.network->cmd_recv_len,FTP_SOCKET_TIMEOUT); + if (ret){ + goto operation_failed; + }else{ + if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_CLOSE_CONNECT, 3)){ + LUAT_DEBUG_PRINT("ftp LIST wrong"); + goto operation_failed; + } + } + ftp_state = FTP_SUCCESS_DATA; + l_ftp_cb(ftp_state); + break; + } + luat_ftp_cmd_send(&g_s_ftp, g_s_ftp.network->cmd_send_data, strlen((const char *)(g_s_ftp.network->cmd_send_data)),FTP_SOCKET_TIMEOUT); + ret = luat_ftp_cmd_recv(&g_s_ftp,g_s_ftp.network->cmd_recv_data,&g_s_ftp.network->cmd_recv_len,FTP_SOCKET_TIMEOUT); + if (ret){ + goto operation_failed; + }else{ + if (memcmp(g_s_ftp.network->cmd_send_data, "NOOP", 4)==0){ + if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_COMMAND_OK, 3)){ + LUAT_DEBUG_PRINT("ftp COMMAND wrong"); + } + }else if(memcmp(g_s_ftp.network->cmd_send_data, "TYPE", 4)==0){ + if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_COMMAND_OK, 3)){ + LUAT_DEBUG_PRINT("ftp COMMAND wrong"); + } + }else if(memcmp(g_s_ftp.network->cmd_send_data, "SYST", 4)==0){ + if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_SYSTEM_TYPE, 3)){ + LUAT_DEBUG_PRINT("ftp COMMAND wrong"); + } + }else if(memcmp(g_s_ftp.network->cmd_send_data, "PWD", 3)==0){ + if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_PATHNAME_OK, 3)){ + LUAT_DEBUG_PRINT("ftp COMMAND wrong"); + } + }else if(memcmp(g_s_ftp.network->cmd_send_data, "MKD", 3)==0){ + if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_PATHNAME_OK, 3)){ + LUAT_DEBUG_PRINT("ftp COMMAND wrong"); + } + }else if(memcmp(g_s_ftp.network->cmd_send_data, "CWD", 3)==0){ + if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_FILE_REQUESTED_OK, 3)){ + LUAT_DEBUG_PRINT("ftp COMMAND wrong"); + } + }else if(memcmp(g_s_ftp.network->cmd_send_data, "CDUP", 4)==0){ + if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_FILE_REQUESTED_OK, 3)){ + LUAT_DEBUG_PRINT("ftp COMMAND wrong"); + } + }else if(memcmp(g_s_ftp.network->cmd_send_data, "RMD", 3)==0){ + if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_FILE_REQUESTED_OK, 3)){ + LUAT_DEBUG_PRINT("ftp COMMAND wrong"); + } + }else if(memcmp(g_s_ftp.network->cmd_send_data, "DELE", 4)==0){ + if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_FILE_REQUESTED_OK, 3)){ + LUAT_DEBUG_PRINT("ftp COMMAND wrong"); + } + }else if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_DATA_CON_FAIL, 3)==0){ + LUAT_DEBUG_PRINT("ftp need pasv_connect"); + + + } + } + OS_BufferWrite(&g_s_ftp.result_buffer, g_s_ftp.network->cmd_recv_data, g_s_ftp.network->cmd_recv_len); + ftp_state = FTP_SUCCESS_DATA; + l_ftp_cb(ftp_state); + break; + default: + break; + } + continue; +operation_failed: + if(g_s_ftp.is_fota) + { + luat_fota_done(g_s_ftp.context) + g_s_ftp.is_fota = 0; + } + ftp_state = FTP_ERROR; + l_ftp_cb(ftp_state); + } + ftp_state = FTP_SUCCESS_NO_DATA; + luat_ftp_cmd_send(&g_s_ftp, (uint8_t*)"QUIT\r\n", strlen("QUIT\r\n"),FTP_SOCKET_TIMEOUT); + ret = luat_ftp_cmd_recv(&g_s_ftp,g_s_ftp.network->cmd_recv_data,&g_s_ftp.network->cmd_recv_len,FTP_SOCKET_TIMEOUT); + if (ret){ + ftp_state = FTP_ERROR; + }else{ + if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_CLOSE_CONTROL, 3)){ + LUAT_DEBUG_PRINT("ftp QUIT wrong"); + ftp_state = FTP_ERROR; + } + } + OS_BufferWrite(&g_s_ftp.result_buffer, g_s_ftp.network->cmd_recv_data, g_s_ftp.network->cmd_recv_len); + if (ftp_state == FTP_SUCCESS_NO_DATA) ftp_state = FTP_SUCCESS_DATA; + l_ftp_cb(ftp_state); + luat_ftp_release(); + g_s_ftp.task_handle = NULL; + luat_rtos_task_delete(task_handle); + return; +wait_event_and_out: + while(1) + { + luat_rtos_event_recv(g_s_ftp.task_handle, 0, &task_event, NULL, LUAT_WAIT_FOREVER); + if (task_event.ID >= FTP_EVENT_LOGIN && task_event.ID <= FTP_EVENT_CLOSE) + { + luat_ftp_release(); + ftp_state = FTP_ERROR; + l_ftp_cb(ftp_state); + g_s_ftp.task_handle = NULL; + luat_rtos_task_delete(task_handle); + return; + } + } +} +int luat_ftp_login(uint8_t adapter,const char * ip_addr,uint16_t port,const char * username,const char * password,luat_ftp_tls_t* luat_ftp_tls,luat_ftp_cb_t ftp_cb){ + if (g_s_ftp.network){ + LUAT_DEBUG_PRINT("ftp already login, please close first"); + return FTP_ERROR_STATE; + } + g_s_ftp.network = (luat_ftp_network_t *)luat_heap_malloc(sizeof(luat_ftp_network_t)); + if (!g_s_ftp.network){ + LUAT_DEBUG_PRINT("out of memory when malloc g_s_ftp.network"); + return FTP_ERROR_NO_MEM; + } + memset(g_s_ftp.network, 0, sizeof(luat_ftp_network_t)); + if (ftp_cb){ + g_s_ftp.network->ftp_cb = ftp_cb; + } + g_s_ftp.network->adapter_index = adapter; + if (g_s_ftp.network->adapter_index >= NW_ADAPTER_QTY){ + LUAT_DEBUG_PRINT("bad network adapter index %d", g_s_ftp.network->adapter_index); + return FTP_ERROR_STATE; + } + g_s_ftp.network->cmd_netc = network_alloc_ctrl(g_s_ftp.network->adapter_index); + if (!g_s_ftp.network->cmd_netc){ + LUAT_DEBUG_PRINT("cmd_netc create fail"); + return FTP_ERROR_NO_MEM; + } + g_s_ftp.network->port = port; + if (strlen(ip_addr) > 0 && strlen(ip_addr) < 64) + memcpy(g_s_ftp.network->addr, ip_addr, strlen(ip_addr) + 1); + if (strlen(username) > 0 && strlen(username) < 64) + memcpy(g_s_ftp.network->username, username, strlen(username) + 1); + if (strlen(password) > 0 && strlen(password) < 64) + memcpy(g_s_ftp.network->password, password, strlen(password) + 1); + if (luat_ftp_tls == NULL){ + network_deinit_tls(g_s_ftp.network->cmd_netc); + }else{ + if (network_init_tls(g_s_ftp.network->cmd_netc, (luat_ftp_tls->server_cert || luat_ftp_tls->client_cert)?2:0)){ + return FTP_ERROR_CLOSE; + } + if (luat_ftp_tls->server_cert){ + network_set_server_cert(g_s_ftp.network->cmd_netc, (const unsigned char *)luat_ftp_tls->server_cert, strlen(luat_ftp_tls->server_cert)+1); + } + if (luat_ftp_tls->client_cert){ + network_set_client_cert(g_s_ftp.network->cmd_netc, (const unsigned char *)luat_ftp_tls->client_cert, strlen(luat_ftp_tls->client_cert)+1, + (const unsigned char *)luat_ftp_tls->client_key, strlen(luat_ftp_tls->client_key)+1, + (const unsigned char *)luat_ftp_tls->client_password, strlen(luat_ftp_tls->client_password)+1); + } + } + g_s_ftp.network->ip_addr.type = 0Xff; + // network_set_ip_invaild(&g_s_ftp.network->ip_addr); + int result = luat_rtos_task_create(&g_s_ftp.task_handle, 2*1024, 10, "ftp", ftp_task, NULL, 16); + if (result) { + LUAT_DEBUG_PRINT("创建ftp task失败!! %d", result); + return result; + } + network_init_ctrl(g_s_ftp.network->cmd_netc,g_s_ftp.task_handle, ftp_task_cb, NULL); + network_set_base_mode(g_s_ftp.network->cmd_netc, 1, 30000, 0, 0, 0, 0); + network_set_local_port(g_s_ftp.network->cmd_netc, 0); + luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_LOGIN, 0, 0, 0, LUAT_WAIT_FOREVER); + return 0; +} + +int luat_ftp_command(const char * command){ + if (!g_s_ftp.network){ + LUAT_DEBUG_PRINT("please login first"); + return -1; + } + if (memcmp(command, "NOOP", 4)==0){ + LUAT_DEBUG_PRINT("command: NOOP"); + }else if(memcmp(command, "SYST", 4)==0){ + LUAT_DEBUG_PRINT("command: SYST"); + }else if(memcmp(command, "MKD", 3)==0){ + LUAT_DEBUG_PRINT("command: MKD"); + }else if(memcmp(command, "CWD", 3)==0){ + LUAT_DEBUG_PRINT("command: CWD"); + }else if(memcmp(command, "CDUP", 4)==0){ + LUAT_DEBUG_PRINT("command: CDUP"); + }else if(memcmp(command, "RMD", 3)==0){ + LUAT_DEBUG_PRINT("command: RMD"); + }else if(memcmp(command, "PWD", 3)==0){ + LUAT_DEBUG_PRINT("command: RMD"); + }else if(memcmp(command, "DELE", 4)==0){ + LUAT_DEBUG_PRINT("command: DELE"); + }else if(memcmp(command, "TYPE", 4)==0){ + LUAT_DEBUG_PRINT("command: TYPE"); + }else if(memcmp(command, "LIST", 4)==0){ + LUAT_DEBUG_PRINT("command: LIST"); + }else{ + LUAT_DEBUG_PRINT("not support cmd:%s",command); + return -1; + } + memset(g_s_ftp.network->cmd_send_data,0,FTP_CMD_SEND_MAX); + snprintf_((char *)(g_s_ftp.network->cmd_send_data), FTP_CMD_SEND_MAX, "%s\r\n",command); + luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_COMMAND, 0, 0, 0, 0); + return 0; +} + +int luat_ftp_pull(const char * local_name, const char * remote_name, uint8_t is_fota){ + if (!g_s_ftp.network){ + LUAT_DEBUG_PRINT("please login first"); + return -1; + } + + if (is_fota == 1) + { + g_s_ftp.is_fota = 1; + g_s_ftp.context = luat_fota_init(); + } + else + { + luat_fs_remove(local_name); + if (g_s_ftp.fd) + { + luat_fs_fclose(g_s_ftp.fd); + g_s_ftp.fd = NULL; + } + g_s_ftp.fd = luat_fs_fopen(local_name, "wb+"); + if (g_s_ftp.fd == NULL) { + LUAT_DEBUG_PRINT("open download file fail %s", local_name); + return -1; + } + } + // g_s_ftp.network->local_file_size = luat_fs_fsize(local_name); + memcpy(g_s_ftp.network->remote_name, remote_name, strlen(remote_name) + 1); + luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_PULL, 0, 0, 0, 0); + return 0; +} + +int luat_ftp_close(void){ + if (!g_s_ftp.network){ + LUAT_DEBUG_PRINT("please login first"); + return -1; + } + luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_CLOSE, 0, 0, 0, LUAT_WAIT_FOREVER); + return 0; +} + +int luat_ftp_push(const char * local_name,const char * remote_name){ + if (!g_s_ftp.network){ + LUAT_DEBUG_PRINT("please login first"); + return -1; + } + if (g_s_ftp.fd) + { + luat_fs_fclose(g_s_ftp.fd); + g_s_ftp.fd = NULL; + } + g_s_ftp.fd = luat_fs_fopen(local_name, "rb"); + if (g_s_ftp.fd == NULL) { + LUAT_DEBUG_PRINT("open download file fail %s", local_name); + return -1; + } + g_s_ftp.network->local_file_size = luat_fs_fsize(local_name); + memcpy(g_s_ftp.network->remote_name, remote_name, strlen(remote_name) + 1); + luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_PUSH, 0, 0, 0, LUAT_WAIT_FOREVER); + return 0; +} diff --git a/thirdparty/libftp/xmake.lua b/thirdparty/libftp/xmake.lua new file mode 100644 index 00000000..44262498 --- /dev/null +++ b/thirdparty/libftp/xmake.lua @@ -0,0 +1,17 @@ + +target("libftp") + local LIB_DIR = "$(buildir)/libftp/" + set_kind("static") + add_deps("luatos_lwip_socket") + set_targetdir(LIB_DIR) + + --加入代码和头文件 + add_includedirs("./", + SDK_TOP.."/luatos_lwip_socket/include", + {public = true}) + + add_files("./*.c",{public = true}) + + --自动链接 + LIB_USER = LIB_USER .. SDK_TOP .. LIB_DIR .. "liblibftp.a " +target_end()