luat_ftp_client.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. #include "luat_base.h"
  2. #include "luat_network_adapter.h"
  3. #include "luat_rtos.h"
  4. #include "luat_fs.h"
  5. #include "luat_mem.h"
  6. #include "luat_ftp.h"
  7. #define LUAT_LOG_TAG "ftp"
  8. #include "luat_log.h"
  9. #undef LLOGD
  10. #define LLOGD(format, ...) do {if (g_s_ftp.debug_onoff) {luat_log_log(LUAT_LOG_DEBUG, LUAT_LOG_TAG, format, ##__VA_ARGS__);}} while(0)
  11. luat_ftp_ctrl_t g_s_ftp;
  12. uint32_t luat_ftp_release(void) {
  13. if (!g_s_ftp.network) return 0;
  14. if (g_s_ftp.network->cmd_netc){
  15. network_force_close_socket(g_s_ftp.network->cmd_netc);
  16. network_release_ctrl(g_s_ftp.network->cmd_netc);
  17. g_s_ftp.network->cmd_netc = NULL;
  18. }
  19. if (g_s_ftp.network->data_netc){
  20. network_force_close_socket(g_s_ftp.network->data_netc);
  21. network_release_ctrl(g_s_ftp.network->data_netc);
  22. g_s_ftp.network->data_netc = NULL;
  23. }
  24. luat_heap_free(g_s_ftp.network);
  25. g_s_ftp.network = NULL;
  26. return 0;
  27. }
  28. static uint32_t luat_ftp_data_send(luat_ftp_ctrl_t *ftp_ctrl, uint8_t* send_data, uint32_t send_len) {
  29. if (send_len == 0)
  30. return 0;
  31. uint32_t tx_len = 0;
  32. LLOGD("luat_ftp_data_send data:%d",send_len);
  33. network_tx(g_s_ftp.network->data_netc, send_data, send_len, 0, NULL, 0, &tx_len, 0);
  34. return tx_len;
  35. }
  36. 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) {
  37. if (send_len == 0)
  38. return 0;
  39. uint32_t tx_len = 0;
  40. LLOGD("luat_ftp_cmd_send data:%.*s",send_len,send_data);
  41. network_tx(g_s_ftp.network->cmd_netc, send_data, send_len, 0, NULL, 0, &tx_len, timeout_ms);
  42. return tx_len;
  43. }
  44. static int luat_ftp_cmd_recv(luat_ftp_ctrl_t *ftp_ctrl,uint8_t *recv_data,uint32_t *recv_len,uint32_t timeout_ms){
  45. uint8_t is_break = 0,is_timeout = 0;
  46. int ret = network_wait_rx(g_s_ftp.network->cmd_netc, timeout_ms, &is_break, &is_timeout);
  47. LLOGD("luat_ftp_cmd_recv network_wait_rx ret:%d is_break:%d is_timeout:%d",ret,is_break,is_timeout);
  48. if (ret)
  49. return -1;
  50. if (is_timeout)
  51. return 1;
  52. else if (is_break)
  53. return 2;
  54. return network_rx(g_s_ftp.network->cmd_netc, recv_data, FTP_CMD_RECV_MAX, 0, NULL, NULL, recv_len);
  55. }
  56. static int32_t luat_ftp_data_callback(void *data, void *param){
  57. OS_EVENT *event = (OS_EVENT *)data;
  58. uint8_t *rx_buffer;
  59. int ret = 0;
  60. uint32_t rx_len = 0;
  61. if (!g_s_ftp.network)
  62. {
  63. return 0;
  64. }
  65. // LLOGD("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);
  66. LLOGD("luat_ftp_data_callback %d %d",event->ID - EV_NW_RESULT_BASE, event->Param1);
  67. if (event->Param1){
  68. if (EV_NW_RESULT_CONNECT == event->ID)
  69. {
  70. luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_DATA_CONNECT, 0xffffffff, 0, 0, LUAT_WAIT_FOREVER);
  71. }
  72. else
  73. {
  74. luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_DATA_CLOSED, 0, 0, 0, LUAT_WAIT_FOREVER);
  75. }
  76. return -1;
  77. }
  78. switch (event->ID)
  79. {
  80. case EV_NW_RESULT_TX:
  81. luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_DATA_TX_DONE, 0, 0, 0, LUAT_WAIT_FOREVER);
  82. break;
  83. case EV_NW_RESULT_EVENT:
  84. rx_buffer = NULL;
  85. uint8_t tmpbuff[4];
  86. do
  87. {
  88. // 先读取长度
  89. ret = network_rx(g_s_ftp.network->data_netc, NULL, 0, 0, NULL, NULL, &rx_len);
  90. if (rx_len <= 0) {
  91. // 没数据? 那也读一次, 然后退出
  92. network_rx(g_s_ftp.network->data_netc, tmpbuff, 4, 0, NULL, NULL, &rx_len);
  93. break;
  94. }
  95. if (rx_len > 2048)
  96. rx_len = 2048;
  97. rx_buffer = luat_heap_malloc(rx_len);
  98. // 如果rx_buffer == NULL, 内存炸了
  99. if (rx_buffer == NULL) {
  100. LLOGE("out of memory when malloc ftp buff");
  101. network_close(g_s_ftp.network->data_netc, 0);
  102. return -1;
  103. }
  104. ret = network_rx(g_s_ftp.network->data_netc, rx_buffer, rx_len, 0, NULL, NULL, &rx_len);
  105. // LLOGD("luat_ftp_data_callback network_rx ret:%d rx_len:%d",ret,rx_len);
  106. if (!ret && rx_len > 0)
  107. {
  108. if (g_s_ftp.fd)
  109. {
  110. luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_DATA_WRITE_FILE, (uint32_t)rx_buffer, rx_len, 0, LUAT_WAIT_FOREVER);
  111. rx_buffer = NULL;
  112. continue;
  113. }
  114. else
  115. {
  116. OS_BufferWrite(&g_s_ftp.result_buffer, rx_buffer, rx_len);
  117. }
  118. }
  119. luat_heap_free(rx_buffer);
  120. rx_buffer = NULL;
  121. } while (!ret && rx_len);
  122. if (rx_buffer)
  123. luat_heap_free(rx_buffer);
  124. rx_buffer = NULL;
  125. break;
  126. case EV_NW_RESULT_CLOSE:
  127. luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_DATA_CLOSED, 0, 0, 0, LUAT_WAIT_FOREVER);
  128. return 0;
  129. break;
  130. case EV_NW_RESULT_CONNECT:
  131. luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_DATA_CONNECT, 0, 0, 0, LUAT_WAIT_FOREVER);
  132. break;
  133. case EV_NW_RESULT_LINK:
  134. return 0;
  135. }
  136. ret = network_wait_event(g_s_ftp.network->data_netc, NULL, 0, NULL);
  137. if (ret < 0){
  138. network_close(g_s_ftp.network->data_netc, 0);
  139. return -1;
  140. }
  141. return 0;
  142. }
  143. static int32_t ftp_task_cb(void *pdata, void *param)
  144. {
  145. OS_EVENT *event = pdata;
  146. if (event->ID >= FTP_EVENT_LOGIN && event->ID <= FTP_EVENT_PUSH)
  147. {
  148. LLOGE("last cmd not finish, ignore %d,%u,%u,%x", event->ID - USER_EVENT_ID_START, event->Param1, event->Param2, param);
  149. return -1;
  150. }
  151. switch(event->ID)
  152. {
  153. case FTP_EVENT_DATA_WRITE_FILE:
  154. if (g_s_ftp.fd)
  155. {
  156. luat_fs_fwrite((void*)event->Param1, event->Param2, 1, g_s_ftp.fd);
  157. luat_heap_free((void*)event->Param1);
  158. }
  159. break;
  160. case FTP_EVENT_DATA_TX_DONE:
  161. g_s_ftp.network->upload_done_size = (size_t)g_s_ftp.network->data_netc->ack_size;
  162. if (g_s_ftp.network->upload_done_size >= g_s_ftp.network->local_file_size)
  163. {
  164. LLOGD("ftp data upload done!");
  165. network_close(g_s_ftp.network->data_netc, 0);
  166. }
  167. break;
  168. case FTP_EVENT_DATA_CONNECT:
  169. if (g_s_ftp.network->data_netc_connecting)
  170. {
  171. g_s_ftp.network->data_netc_connecting = 0;
  172. g_s_ftp.network->data_netc_online = !event->Param1;
  173. }
  174. break;
  175. case FTP_EVENT_DATA_CLOSED:
  176. LLOGD("ftp data channel close");
  177. g_s_ftp.network->data_netc_online = 0;
  178. if (g_s_ftp.network->data_netc)
  179. {
  180. network_force_close_socket(g_s_ftp.network->data_netc);
  181. network_release_ctrl(g_s_ftp.network->data_netc);
  182. g_s_ftp.network->data_netc = NULL;
  183. }
  184. break;
  185. case FTP_EVENT_CLOSE:
  186. g_s_ftp.is_run = 0;
  187. break;
  188. default:
  189. // LLOGE("ignore %x,%x,%x", event->ID, param, EV_NW_RESULT_EVENT);
  190. break;
  191. }
  192. return 0;
  193. }
  194. static int luat_ftp_pasv_connect(luat_ftp_ctrl_t *ftp_ctrl,uint32_t timeout_ms){
  195. char h1[4]={0},h2[4]={0},h3[4]={0},h4[4]={0},p1[4]={0},p2[4]={0},data_addr[64]={0};
  196. uint8_t port1,port2;
  197. uint16_t data_port;
  198. luat_ftp_cmd_send(&g_s_ftp, (uint8_t*)"PASV\r\n", strlen("PASV\r\n"),FTP_SOCKET_TIMEOUT);
  199. // g_s_ftp.data_transfer_done = 0;
  200. 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);
  201. if (ret){
  202. return -1;
  203. }else{
  204. LLOGD("luat_ftp_pasv_connect cmd_recv_data %s",g_s_ftp.network->cmd_recv_data);
  205. if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_ENTER_PASSIVE, 3)){
  206. LLOGD("ftp pasv_connect wrong");
  207. return -1;
  208. }
  209. }
  210. char *temp = memchr(g_s_ftp.network->cmd_recv_data, '(', strlen((const char *)(g_s_ftp.network->cmd_recv_data)));
  211. char *temp1 = memchr(temp+1, ',', strlen(temp)-1);
  212. memcpy(h1, temp+1, temp1-temp-1);
  213. char *temp2 = memchr(temp1+1, ',', strlen(temp1)-1);
  214. memcpy(h2, temp1+1, temp2-temp1-1);
  215. char *temp3 = memchr(temp2+1, ',', strlen(temp2)-1);
  216. memcpy(h3, temp2+1, temp3-temp2-1);
  217. char *temp4 = memchr(temp3+1, ',', strlen(temp3)-1);
  218. memcpy(h4, temp3+1, temp4-temp3-1);
  219. char *temp5 = memchr(temp4+1, ',', strlen(temp4)-1);
  220. memcpy(p1, temp4+1, temp5-temp4-1);
  221. char *temp6 = memchr(temp5+1, ')', strlen(temp5)-1);
  222. memcpy(p2, temp5+1, temp6-temp5-1);
  223. snprintf_(data_addr, 64, "%s.%s.%s.%s",h1,h2,h3,h4);
  224. port1 = (uint8_t)atoi(p1);
  225. port2 = (uint8_t)atoi(p2);
  226. data_port = port1 * 256 + port2;
  227. LLOGD("data_addr:%s data_port:%d",data_addr,data_port);
  228. 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){
  229. memset(data_addr,0,64);
  230. LLOGD("g_s_ftp.network->addr:%s",g_s_ftp.network->addr);
  231. memcpy(data_addr, g_s_ftp.network->addr, strlen(g_s_ftp.network->addr)+1);
  232. }
  233. LLOGD("data_addr:%s data_port:%d",data_addr,data_port);
  234. if (g_s_ftp.network->data_netc)
  235. {
  236. LLOGE("data_netc already create");
  237. return -1;
  238. }
  239. g_s_ftp.network->data_netc = network_alloc_ctrl(g_s_ftp.network->adapter_index);
  240. if (!g_s_ftp.network->data_netc){
  241. LLOGE("data_netc create fail");
  242. return -1;
  243. }
  244. network_init_ctrl(g_s_ftp.network->data_netc,NULL, luat_ftp_data_callback, g_s_ftp.network);
  245. network_set_base_mode(g_s_ftp.network->data_netc, 1, 10000, 0, 0, 0, 0);
  246. network_set_local_port(g_s_ftp.network->data_netc, 0);
  247. network_deinit_tls(g_s_ftp.network->data_netc);
  248. if(network_connect(g_s_ftp.network->data_netc, data_addr, strlen(data_addr), NULL, data_port, 0)<0){
  249. LLOGE("ftp data network connect fail");
  250. network_force_close_socket(g_s_ftp.network->data_netc);
  251. network_release_ctrl(g_s_ftp.network->data_netc);
  252. g_s_ftp.network->data_netc = NULL;
  253. return -1;
  254. }
  255. uint8_t is_timeout;
  256. OS_EVENT event;
  257. g_s_ftp.network->data_netc_connecting = 1;
  258. g_s_ftp.network->data_netc_online = 0;
  259. while(g_s_ftp.network->data_netc_connecting)
  260. {
  261. if (network_wait_event(g_s_ftp.network->cmd_netc, &event, timeout_ms, &is_timeout))
  262. {
  263. return -1;
  264. }
  265. if (is_timeout)
  266. {
  267. return -1;
  268. }
  269. if (event.ID)
  270. {
  271. ftp_task_cb(&event, NULL);
  272. }
  273. else
  274. {
  275. if (g_s_ftp.network->cmd_netc->new_rx_flag)
  276. {
  277. 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);
  278. LLOGD("ftp cmd rx %.*s", g_s_ftp.network->cmd_recv_len, g_s_ftp.network->cmd_recv_data);
  279. }
  280. }
  281. }
  282. if (g_s_ftp.network->data_netc_online)
  283. {
  284. LLOGD("ftp pasv_connect ok");
  285. return 0;
  286. }
  287. return -1;
  288. }
  289. static int ftp_login(void)
  290. {
  291. int ret;
  292. 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)){
  293. LLOGE("ftp network_connect fail");
  294. return -1;
  295. }
  296. 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);
  297. if (ret){
  298. return -1;
  299. }else{
  300. if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_SERVICE_NEW_OK, 3)){
  301. LLOGE("ftp connect error");
  302. return -1;
  303. }
  304. }
  305. LLOGD("ftp connect ok");
  306. memset(g_s_ftp.network->cmd_send_data,0,FTP_CMD_SEND_MAX);
  307. snprintf_((char *)(g_s_ftp.network->cmd_send_data), FTP_CMD_SEND_MAX, "USER %s\r\n",g_s_ftp.network->username);
  308. 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);
  309. 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);
  310. if (ret){
  311. LLOGE("ftp username wrong");
  312. return -1;
  313. }else{
  314. if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_USERNAME_OK, 3)){
  315. LLOGE("ftp username wrong");
  316. return -1;
  317. }
  318. }
  319. LLOGD("ftp username ok");
  320. memset(g_s_ftp.network->cmd_send_data,0,FTP_CMD_SEND_MAX);
  321. snprintf_((char *)(g_s_ftp.network->cmd_send_data), FTP_CMD_SEND_MAX, "PASS %s\r\n",g_s_ftp.network->password);
  322. 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);
  323. 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);
  324. if (ret){
  325. LLOGE("ftp login wrong");
  326. return -1;
  327. }else{
  328. if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_LOGIN_OK, 3)){
  329. LLOGE("ftp login wrong");
  330. return -1;
  331. }
  332. }
  333. LLOGD("ftp login ok");
  334. return 0;
  335. }
  336. static void l_ftp_cb(FTP_SUCCESS_STATE_e state){
  337. if (g_s_ftp.network->ftp_cb){
  338. luat_ftp_cb_t ftp_cb = g_s_ftp.network->ftp_cb;
  339. ftp_cb(&g_s_ftp,state);
  340. }
  341. #ifndef __LUATOS__
  342. OS_DeInitBuffer(&g_s_ftp.result_buffer);
  343. #endif
  344. }
  345. static int find_newline(void)
  346. {
  347. uint32_t pos = 0;
  348. while (pos < g_s_ftp.network->cmd_recv_len)
  349. {
  350. if(('\r' == g_s_ftp.network->cmd_recv_data[pos]) || ('\n' == g_s_ftp.network->cmd_recv_data[pos]))
  351. {
  352. return pos;
  353. }
  354. else
  355. {
  356. pos++;
  357. }
  358. }
  359. return -1;
  360. }
  361. static int pasv_recv(void)
  362. {
  363. int ret;
  364. int pos;
  365. uint8_t rx_finish = 0;
  366. 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);
  367. if (ret){
  368. return -1;
  369. }
  370. LLOGD("%.*s", g_s_ftp.network->cmd_recv_len, g_s_ftp.network->cmd_recv_data);
  371. g_s_ftp.network->cmd_recv_data[g_s_ftp.network->cmd_recv_len] = 0;
  372. if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_FILE_STATUS_OK, 3) && memcmp(g_s_ftp.network->cmd_recv_data, FTP_DATA_CON_OPEN, 3)){
  373. return -1;
  374. }
  375. pos = find_newline();
  376. if (pos >= 0)
  377. {
  378. memmove(g_s_ftp.network->cmd_recv_data, g_s_ftp.network->cmd_recv_data + pos, g_s_ftp.network->cmd_recv_len - pos);
  379. g_s_ftp.network->cmd_recv_len -= pos;
  380. g_s_ftp.network->cmd_recv_data[g_s_ftp.network->cmd_recv_len] = 0;
  381. if (strstr((const char *)(g_s_ftp.network->cmd_recv_data), FTP_CLOSE_CONNECT))
  382. {
  383. rx_finish = 1;
  384. }
  385. }
  386. while(!rx_finish && (g_s_ftp.network->data_netc_online || g_s_ftp.result_buffer.Pos)) //data通道未断开或者已经接收到数据了
  387. {
  388. 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);
  389. if (ret < 0){
  390. LLOGD("rx error!%d", ret);
  391. return -1;
  392. } else if (!ret) {
  393. LLOGD("%.*s", g_s_ftp.network->cmd_recv_len, g_s_ftp.network->cmd_recv_data);
  394. if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_CLOSE_CONNECT, 3)){
  395. return -1;
  396. }
  397. else {
  398. rx_finish = 1;
  399. }
  400. }
  401. }
  402. if (!rx_finish) { //没接收完就断开了
  403. LLOGD("???");
  404. return -1;
  405. }
  406. //等服务器关闭接收通道
  407. if (g_s_ftp.network->data_netc_online) {
  408. ret = luat_ftp_cmd_recv(&g_s_ftp,g_s_ftp.network->cmd_recv_data,&g_s_ftp.network->cmd_recv_len,1000);
  409. if (ret < 0) {
  410. return -1;
  411. }
  412. }
  413. //主动关闭掉接收
  414. if (g_s_ftp.network->data_netc_online && g_s_ftp.network->data_netc) {
  415. network_close(g_s_ftp.network->data_netc, 0);
  416. }
  417. return 0;
  418. }
  419. static void ftp_task(void *param){
  420. FTP_SUCCESS_STATE_e ftp_state = FTP_SUCCESS_NO_DATE;
  421. int ret;
  422. int count = 0;
  423. luat_rtos_task_handle task_handle = g_s_ftp.task_handle;
  424. OS_EVENT task_event;
  425. uint8_t is_timeout = 0;
  426. g_s_ftp.is_run = 1;
  427. luat_rtos_event_recv(g_s_ftp.task_handle, FTP_EVENT_LOGIN, &task_event, NULL, LUAT_WAIT_FOREVER);
  428. if (ftp_login()){
  429. LLOGE("ftp login fail");
  430. ftp_state = FTP_ERROR;
  431. l_ftp_cb(ftp_state);
  432. luat_ftp_release();
  433. g_s_ftp.task_handle = NULL;
  434. luat_rtos_task_delete(task_handle);
  435. return;
  436. }else{
  437. l_ftp_cb(ftp_state);
  438. }
  439. while (g_s_ftp.is_run) {
  440. is_timeout = 0;
  441. ret = network_wait_event(g_s_ftp.network->cmd_netc, &task_event, 3600000, &is_timeout);
  442. if (ret < 0){
  443. LLOGE("ftp network error");
  444. goto wait_event_and_out;
  445. }else if (is_timeout || !task_event.ID){
  446. if (g_s_ftp.network->cmd_netc->new_rx_flag){
  447. network_rx(g_s_ftp.network->cmd_netc, g_s_ftp.network->cmd_recv_data, 1024, 0, NULL, NULL, &ret);
  448. LLOGD("ftp rx %dbyte", ret);
  449. }
  450. continue;
  451. }
  452. ftp_state = FTP_SUCCESS_NO_DATE;
  453. switch (task_event.ID)
  454. {
  455. case FTP_EVENT_LOGIN:
  456. break;
  457. case FTP_EVENT_PULL:
  458. if (g_s_ftp.network->data_netc)
  459. {
  460. network_force_close_socket(g_s_ftp.network->data_netc);
  461. network_release_ctrl(g_s_ftp.network->data_netc);
  462. g_s_ftp.network->data_netc = NULL;
  463. }
  464. if(luat_ftp_pasv_connect(&g_s_ftp,FTP_SOCKET_TIMEOUT)){
  465. LLOGE("ftp pasv_connect fail");
  466. goto operation_failed;
  467. }
  468. snprintf_((char *)(g_s_ftp.network->cmd_send_data), FTP_CMD_SEND_MAX, "RETR %s\r\n",g_s_ftp.network->remote_name);
  469. 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);
  470. if (pasv_recv()) goto operation_failed;
  471. if (g_s_ftp.fd){
  472. luat_fs_fclose(g_s_ftp.fd);
  473. g_s_ftp.fd = NULL;
  474. }
  475. l_ftp_cb(ftp_state);
  476. break;
  477. case FTP_EVENT_PUSH:
  478. if(luat_ftp_pasv_connect(&g_s_ftp,FTP_SOCKET_TIMEOUT)){
  479. LLOGD("ftp pasv_connect fail");
  480. goto operation_failed;
  481. }
  482. memset(g_s_ftp.network->cmd_send_data,0,FTP_CMD_SEND_MAX);
  483. snprintf_((char *)(g_s_ftp.network->cmd_send_data), FTP_CMD_SEND_MAX, "STOR %s\r\n",g_s_ftp.network->remote_name);
  484. 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);
  485. 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);
  486. if (ret){
  487. goto operation_failed;
  488. }else{
  489. LLOGD("%.*s", g_s_ftp.network->cmd_recv_len, g_s_ftp.network->cmd_recv_data);
  490. if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_FILE_STATUS_OK, 3) && memcmp(g_s_ftp.network->cmd_recv_data, FTP_DATA_CON_OPEN, 3)){
  491. LLOGD("ftp STOR wrong");
  492. goto operation_failed;
  493. }
  494. }
  495. uint8_t* buff = luat_heap_malloc(PUSH_BUFF_SIZE);
  496. int offset = 0;
  497. g_s_ftp.network->upload_done_size = 0;
  498. while (1) {
  499. memset(buff, 0, PUSH_BUFF_SIZE);
  500. int len = luat_fs_fread(buff, sizeof(uint8_t), PUSH_BUFF_SIZE, g_s_ftp.fd);
  501. if (len < 1)
  502. break;
  503. luat_ftp_data_send(&g_s_ftp, buff, len);
  504. offset += len;
  505. }
  506. luat_heap_free(buff);
  507. LLOGD("offset:%d file_size:%d",offset,g_s_ftp.network->local_file_size);
  508. 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);
  509. if (g_s_ftp.network->upload_done_size != g_s_ftp.network->local_file_size)
  510. {
  511. LLOGE("upload not finish !!! %d,%d", g_s_ftp.network->upload_done_size, g_s_ftp.network->local_file_size);
  512. }
  513. if (ret){
  514. goto operation_failed;
  515. }else{
  516. if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_CLOSE_CONNECT, 3)){
  517. LLOGD("ftp STOR wrong");
  518. }
  519. }
  520. while (count<3 && g_s_ftp.network->data_netc_online!=0){
  521. 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);
  522. count++;
  523. }
  524. if (g_s_ftp.fd){
  525. luat_fs_fclose(g_s_ftp.fd);
  526. g_s_ftp.fd = NULL;
  527. }
  528. l_ftp_cb(ftp_state);
  529. break;
  530. case FTP_EVENT_CLOSE:
  531. g_s_ftp.is_run = 0;
  532. break;
  533. case FTP_EVENT_COMMAND:
  534. OS_DeInitBuffer(&g_s_ftp.result_buffer);
  535. if(!memcmp(g_s_ftp.network->cmd_send_data, "LIST", 4))
  536. {
  537. if(luat_ftp_pasv_connect(&g_s_ftp,FTP_SOCKET_TIMEOUT)){
  538. LLOGD("ftp pasv_connect fail");
  539. goto operation_failed;
  540. }
  541. 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);
  542. if (pasv_recv()) goto operation_failed;
  543. ftp_state = FTP_SUCCESS_DATE;
  544. l_ftp_cb(ftp_state);
  545. break;
  546. }
  547. 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);
  548. 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);
  549. if (ret){
  550. goto operation_failed;
  551. }else{
  552. if (memcmp(g_s_ftp.network->cmd_send_data, "NOOP", 4)==0){
  553. if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_COMMAND_OK, 3)){
  554. LLOGD("ftp COMMAND wrong");
  555. }
  556. }else if(memcmp(g_s_ftp.network->cmd_send_data, "TYPE", 4)==0){
  557. if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_COMMAND_OK, 3)){
  558. LLOGD("ftp COMMAND wrong");
  559. }
  560. }else if(memcmp(g_s_ftp.network->cmd_send_data, "SYST", 4)==0){
  561. if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_SYSTEM_TYPE, 3)){
  562. LLOGD("ftp COMMAND wrong");
  563. }
  564. }else if(memcmp(g_s_ftp.network->cmd_send_data, "PWD", 3)==0){
  565. if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_PATHNAME_OK, 3)){
  566. LLOGD("ftp COMMAND wrong");
  567. }
  568. }else if(memcmp(g_s_ftp.network->cmd_send_data, "MKD", 3)==0){
  569. if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_PATHNAME_OK, 3)){
  570. LLOGD("ftp COMMAND wrong");
  571. }
  572. }else if(memcmp(g_s_ftp.network->cmd_send_data, "CWD", 3)==0){
  573. if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_FILE_REQUESTED_OK, 3)){
  574. LLOGD("ftp COMMAND wrong");
  575. }
  576. }else if(memcmp(g_s_ftp.network->cmd_send_data, "CDUP", 4)==0){
  577. if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_FILE_REQUESTED_OK, 3)){
  578. LLOGD("ftp COMMAND wrong");
  579. }
  580. }else if(memcmp(g_s_ftp.network->cmd_send_data, "RMD", 3)==0){
  581. if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_FILE_REQUESTED_OK, 3)){
  582. LLOGD("ftp COMMAND wrong");
  583. }
  584. }else if(memcmp(g_s_ftp.network->cmd_send_data, "DELE", 4)==0){
  585. if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_FILE_REQUESTED_OK, 3)){
  586. LLOGD("ftp COMMAND wrong");
  587. }
  588. }else if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_DATA_CON_FAIL, 3)==0){
  589. LLOGD("ftp need pasv_connect");
  590. }
  591. }
  592. OS_BufferWrite(&g_s_ftp.result_buffer, g_s_ftp.network->cmd_recv_data, g_s_ftp.network->cmd_recv_len);
  593. ftp_state = FTP_SUCCESS_DATE;
  594. l_ftp_cb(ftp_state);
  595. break;
  596. default:
  597. break;
  598. }
  599. continue;
  600. operation_failed:
  601. if (g_s_ftp.fd){
  602. luat_fs_fclose(g_s_ftp.fd);
  603. g_s_ftp.fd = NULL;
  604. }
  605. ftp_state = FTP_ERROR;
  606. l_ftp_cb(ftp_state);
  607. }
  608. ftp_state = FTP_SUCCESS_NO_DATE;
  609. luat_ftp_cmd_send(&g_s_ftp, (uint8_t*)"QUIT\r\n", strlen("QUIT\r\n"),FTP_SOCKET_TIMEOUT);
  610. 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);
  611. if (ret){
  612. ftp_state = FTP_ERROR;
  613. }else{
  614. if (memcmp(g_s_ftp.network->cmd_recv_data, FTP_CLOSE_CONTROL, 3)){
  615. LLOGE("ftp QUIT wrong");
  616. ftp_state = FTP_ERROR;
  617. }
  618. }
  619. OS_BufferWrite(&g_s_ftp.result_buffer, g_s_ftp.network->cmd_recv_data, g_s_ftp.network->cmd_recv_len);
  620. if (ftp_state == FTP_SUCCESS_NO_DATE) ftp_state = FTP_SUCCESS_DATE;
  621. l_ftp_cb(ftp_state);
  622. luat_ftp_release();
  623. g_s_ftp.task_handle = NULL;
  624. luat_rtos_task_delete(task_handle);
  625. return;
  626. wait_event_and_out:
  627. while(1)
  628. {
  629. luat_rtos_event_recv(g_s_ftp.task_handle, 0, &task_event, NULL, LUAT_WAIT_FOREVER);
  630. if (task_event.ID >= FTP_EVENT_LOGIN && task_event.ID <= FTP_EVENT_CLOSE)
  631. {
  632. luat_ftp_release();
  633. ftp_state = FTP_ERROR;
  634. l_ftp_cb(ftp_state);
  635. g_s_ftp.task_handle = NULL;
  636. luat_rtos_task_delete(task_handle);
  637. return;
  638. }
  639. }
  640. }
  641. 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){
  642. if (g_s_ftp.network){
  643. LLOGE("ftp already login, please close first");
  644. return FTP_ERROR_STATE;
  645. }
  646. g_s_ftp.network = (luat_ftp_network_t *)luat_heap_malloc(sizeof(luat_ftp_network_t));
  647. if (!g_s_ftp.network){
  648. LLOGE("out of memory when malloc g_s_ftp.network");
  649. return FTP_ERROR_NO_MEM;
  650. }
  651. memset(g_s_ftp.network, 0, sizeof(luat_ftp_network_t));
  652. if (ftp_cb){
  653. g_s_ftp.network->ftp_cb = ftp_cb;
  654. }
  655. g_s_ftp.network->adapter_index = adapter;
  656. if (g_s_ftp.network->adapter_index >= NW_ADAPTER_QTY){
  657. LLOGE("bad network adapter index %d", g_s_ftp.network->adapter_index);
  658. return FTP_ERROR_STATE;
  659. }
  660. g_s_ftp.network->cmd_netc = network_alloc_ctrl(g_s_ftp.network->adapter_index);
  661. if (!g_s_ftp.network->cmd_netc){
  662. LLOGE("cmd_netc create fail");
  663. return FTP_ERROR_NO_MEM;
  664. }
  665. g_s_ftp.network->port = port;
  666. if (strlen(ip_addr) > 0 && strlen(ip_addr) < 64)
  667. memcpy(g_s_ftp.network->addr, ip_addr, strlen(ip_addr) + 1);
  668. if (strlen(username) > 0 && strlen(username) < 64)
  669. memcpy(g_s_ftp.network->username, username, strlen(username) + 1);
  670. if (strlen(password) > 0 && strlen(password) < 64)
  671. memcpy(g_s_ftp.network->password, password, strlen(password) + 1);
  672. if (luat_ftp_tls == NULL){
  673. network_deinit_tls(g_s_ftp.network->cmd_netc);
  674. }else{
  675. if (network_init_tls(g_s_ftp.network->cmd_netc, (luat_ftp_tls->server_cert || luat_ftp_tls->client_cert)?2:0)){
  676. return FTP_ERROR_CLOSE;
  677. }
  678. if (luat_ftp_tls->server_cert){
  679. 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);
  680. }
  681. if (luat_ftp_tls->client_cert){
  682. 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,
  683. (const unsigned char *)luat_ftp_tls->client_key, strlen(luat_ftp_tls->client_key)+1,
  684. (const unsigned char *)luat_ftp_tls->client_password, strlen(luat_ftp_tls->client_password)+1);
  685. }
  686. }
  687. network_set_ip_invaild(&g_s_ftp.network->ip_addr);
  688. int result = luat_rtos_task_create(&g_s_ftp.task_handle, 2*1024, 10, "ftp", ftp_task, NULL, 16);
  689. if (result) {
  690. LLOGE("创建ftp task失败!! %d", result);
  691. return result;
  692. }
  693. network_init_ctrl(g_s_ftp.network->cmd_netc,g_s_ftp.task_handle, ftp_task_cb, NULL);
  694. network_set_base_mode(g_s_ftp.network->cmd_netc, 1, 30000, 0, 0, 0, 0);
  695. network_set_local_port(g_s_ftp.network->cmd_netc, 0);
  696. luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_LOGIN, 0, 0, 0, LUAT_WAIT_FOREVER);
  697. return 0;
  698. }
  699. int luat_ftp_command(const char * command){
  700. if (!g_s_ftp.network){
  701. LLOGE("please login first");
  702. return -1;
  703. }
  704. if (memcmp(command, "NOOP", 4)==0){
  705. LLOGD("command: NOOP");
  706. }else if(memcmp(command, "SYST", 4)==0){
  707. LLOGD("command: SYST");
  708. }else if(memcmp(command, "MKD", 3)==0){
  709. LLOGD("command: MKD");
  710. }else if(memcmp(command, "CWD", 3)==0){
  711. LLOGD("command: CWD");
  712. }else if(memcmp(command, "CDUP", 4)==0){
  713. LLOGD("command: CDUP");
  714. }else if(memcmp(command, "RMD", 3)==0){
  715. LLOGD("command: RMD");
  716. }else if(memcmp(command, "PWD", 3)==0){
  717. LLOGD("command: RMD");
  718. }else if(memcmp(command, "DELE", 4)==0){
  719. LLOGD("command: DELE");
  720. }else if(memcmp(command, "TYPE", 4)==0){
  721. LLOGD("command: TYPE");
  722. }else if(memcmp(command, "LIST", 4)==0){
  723. LLOGD("command: LIST");
  724. }else{
  725. LLOGE("not support cmd:%s",command);
  726. return -1;
  727. }
  728. memset(g_s_ftp.network->cmd_send_data,0,FTP_CMD_SEND_MAX);
  729. snprintf_((char *)(g_s_ftp.network->cmd_send_data), FTP_CMD_SEND_MAX, "%s\r\n",command);
  730. luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_COMMAND, 0, 0, 0, 0);
  731. return 0;
  732. }
  733. int luat_ftp_pull(const char * local_name,const char * remote_name){
  734. if (!g_s_ftp.network){
  735. LLOGE("please login first");
  736. return -1;
  737. }
  738. luat_fs_remove(local_name);
  739. if (g_s_ftp.fd)
  740. {
  741. luat_fs_fclose(g_s_ftp.fd);
  742. g_s_ftp.fd = NULL;
  743. }
  744. g_s_ftp.fd = luat_fs_fopen(local_name, "wb+");
  745. if (g_s_ftp.fd == NULL) {
  746. LLOGE("open download file fail %s", local_name);
  747. return -1;
  748. }
  749. g_s_ftp.network->local_file_size = luat_fs_fsize(local_name);
  750. memcpy(g_s_ftp.network->remote_name, remote_name, strlen(remote_name) + 1);
  751. luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_PULL, 0, 0, 0, 0);
  752. return 0;
  753. }
  754. int luat_ftp_close(void){
  755. if (!g_s_ftp.network){
  756. LLOGE("please login first");
  757. return -1;
  758. }
  759. luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_CLOSE, 0, 0, 0, LUAT_WAIT_FOREVER);
  760. return 0;
  761. }
  762. int luat_ftp_push(const char * local_name,const char * remote_name){
  763. if (!g_s_ftp.network){
  764. LLOGE("please login first");
  765. return -1;
  766. }
  767. if (g_s_ftp.fd)
  768. {
  769. luat_fs_fclose(g_s_ftp.fd);
  770. g_s_ftp.fd = NULL;
  771. }
  772. g_s_ftp.fd = luat_fs_fopen(local_name, "rb");
  773. if (g_s_ftp.fd == NULL) {
  774. LLOGE("open download file fail %s", local_name);
  775. return -1;
  776. }
  777. g_s_ftp.network->local_file_size = luat_fs_fsize(local_name);
  778. memcpy(g_s_ftp.network->remote_name, remote_name, strlen(remote_name) + 1);
  779. luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_PUSH, 0, 0, 0, LUAT_WAIT_FOREVER);
  780. return 0;
  781. }
  782. void luat_ftp_debug(uint8_t on_off) {g_s_ftp.debug_onoff = on_off;}