| /************************************************************* | 
 |  Description: | 
 |  $file_description$ | 
 |  Author: | 
 |  LiuBin | 
 |  Date: | 
 |  2020/10/28 11:49:08 | 
 |  *************************************************************/ | 
 | #include "mbtk_ftp.h" | 
 | #include "mbtk_list.h" | 
 | #include "mbtk_sock.h" | 
 | #include "mbtk_str.h" | 
 | #include "mbtk_sock2.h" | 
 | #include<linux/msg.h> | 
 |  | 
 | /************************************************************* | 
 |  Constants and Macros | 
 |  *************************************************************/ | 
 | #define FTP_HANDLE_MAX 5 | 
 | #define FTP_ANONYMOUS_USER "Anonymous" | 
 | #define FTP_ANONYMOUS_PASS "@" | 
 |  | 
 | //#define FTP_RESUME_DEBUG | 
 |  | 
 | #ifdef MBTK_PLATFORM_QCOMM | 
 | #define FTP_TIMEOUT 60000    // 60s | 
 | #else | 
 | #define FTP_TIMEOUT 3000    // 3s | 
 | #endif | 
 |  | 
 | /************************************************************* | 
 |  typedef struct:local at | 
 |  *************************************************************/ | 
 | typedef struct | 
 | { | 
 |     char host[64]; | 
 |     uint16 port; | 
 |     mbtk_ftp_auth_type_enum auth_type; | 
 |     bool ftp_type; | 
 |     bool use_cert; | 
 |     char name[FTP_SERVER_USER_NAME_MAX+1]; | 
 |     char pass[FTP_SERVER_USER_PASS_MAX+1]; | 
 |     mbtk_ftp_handle at_ftp_handle; | 
 |     char remote_path[MBTK_FTP_FILE_NAME_MAX+1]; | 
 |     char local_path[MBTK_FTP_FILE_NAME_MAX+1]; | 
 |     int rest_size; | 
 |     int read_size; | 
 |     int put_len; | 
 | } mbtk_at_init_parameter; | 
 |  | 
 | mbtk_at_init_parameter mbtk_at_ftp_par={0}; | 
 |  | 
 | /************************************************************* | 
 |  Variables:local | 
 |  *************************************************************/ | 
 | static list_node_t *ftp_client_list = NULL; | 
 |  | 
 | /************************************************************* | 
 |  Variables:public | 
 |  *************************************************************/ | 
 |  | 
 | /************************************************************* | 
 |  Local Function Declaration | 
 |  *************************************************************/ | 
 |  | 
 | /************************************************************* | 
 |  Local Function Definitions | 
 |  *************************************************************/ | 
 | static bool ftp_ch_is_space(char ch) | 
 | { | 
 |     if (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t') | 
 |         return true; | 
 |  | 
 |     return false; | 
 | } | 
 |  | 
 | static const char* ftp_str_next(const char* str, char *result, uint32 len) | 
 | { | 
 |     memset(result, 0x0, len); | 
 |     const char* ptr = str; | 
 |     const char* ptr_result; | 
 |     while (*ptr && ftp_ch_is_space(*ptr)) | 
 |     { | 
 |         ptr++; | 
 |     } | 
 |     if (*ptr == '\0') | 
 |     { | 
 |         return NULL; | 
 |     } | 
 |     // Point to first no space char. | 
 |     ptr_result = ptr; | 
 |     while (*ptr && !ftp_ch_is_space(*ptr)) | 
 |     { | 
 |         ptr++; | 
 |     } | 
 |  | 
 |     // Point to first space char or '\0'. | 
 |     memcpy(result, ptr_result, ptr - ptr_result); | 
 |  | 
 |     if (*ptr == '\0') | 
 |     { | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     return ptr; | 
 | } | 
 |  | 
 | static int ftp_cmd_handle(mbtk_ftp_info_s *info, const void *cmd, void *rsp, | 
 |                           uint32 *rsp_len) | 
 | { | 
 |     int err; | 
 |     int rsp_code; | 
 |     int len = strlen((char*) cmd); | 
 |     // Write cmd | 
 |     if(info->auth_type != 0) | 
 |     { | 
 |         mbtk_sock_write(info->ftp_ssl_handle,info->session,cmd,len,60000,&err); | 
 |         if(err!=0) | 
 |         { | 
 |             printf("\nmbtk_sock_write error:%d\n",err); | 
 |             return err; | 
 |         } | 
 |     } | 
 |     else | 
 |     { | 
 |         if (sock_write(&info->net_info, &info->sock_info[FTP_SOCK_CTRL], cmd, len, 60000, &err) | 
 |             != len) | 
 |         { | 
 |             LOGE("Socket write fail[err = %d].", err); | 
 |             return -1; | 
 |         } | 
 |     } | 
 |  | 
 |     // Read cmd response | 
 |     if (rsp != NULL && *rsp_len > 0) | 
 |     { | 
 |     read_angin_1: | 
 |         memset(rsp, 0x0, *rsp_len); | 
 |         if(info->auth_type != 0) | 
 |         { | 
 |             unsigned char mbtk_ftp_ssl_read_buf[16384 + 1]; | 
 |             len = mbtk_sock_read(info->ftp_ssl_handle,info->session,mbtk_ftp_ssl_read_buf,sizeof(mbtk_ftp_ssl_read_buf),FTP_TIMEOUT,&err); | 
 |             if(err != 0) | 
 |             { | 
 |                 printf("\n mbtk_sock_read error:%d \n",err); | 
 |             } | 
 |             rsp_code = atoi(mbtk_ftp_ssl_read_buf); | 
 |             printf("%s -> Code:%d; RSP:%s\n", (char*)cmd, rsp_code, (char* )mbtk_ftp_ssl_read_buf); | 
 |             if (rsp_code == 0) | 
 |             { | 
 |                 goto read_angin_1; | 
 |             } | 
 |             memcpy((char* )rsp, mbtk_ftp_ssl_read_buf, strlen(mbtk_ftp_ssl_read_buf)); | 
 |             //printf("\nrsp = %s\n",(char* )rsp); | 
 |             return rsp_code; | 
 |         } | 
 |         else | 
 |         { | 
 |             len = sock_readline(&info->net_info, &info->sock_info[FTP_SOCK_CTRL], rsp, *rsp_len, FTP_TIMEOUT,&err); | 
 |         } | 
 |         if (len <= 0) | 
 |         { | 
 |             LOGE("Socket read fail[len = %d].", len); | 
 |             return -1; | 
 |         } | 
 |         rsp_code = atoi(rsp); | 
 |         LOGI("%s -> Code:%d; RSP:%s", (char*)cmd, rsp_code, (char* )rsp); | 
 |         //log_hex("FTP_RSP",(char* )rsp,len); | 
 |  | 
 |         if (rsp_code == 0) | 
 |         { | 
 |             goto read_angin_1; | 
 |         } | 
 |  | 
 |         *rsp_len = len; | 
 |     } | 
 |     else | 
 |     { | 
 |         char buff[1024]; | 
 |  | 
 |     read_angin_2: | 
 |         memset(buff, 0x0, 1024); | 
 |         if(info->auth_type != 0) | 
 |         { | 
 |             unsigned char mbtk_ftp_ssl_read_buf[16384 + 1]; | 
 |             len = mbtk_sock_read(info->ftp_ssl_handle,info->session,mbtk_ftp_ssl_read_buf,sizeof(mbtk_ftp_ssl_read_buf),FTP_TIMEOUT,&err); | 
 |             if(err != 0) | 
 |             { | 
 |                 printf("\nmbtk_sock_read error:%d\n",err); | 
 |             } | 
 |             rsp_code = atoi(mbtk_ftp_ssl_read_buf); | 
 |             printf("%s -> Code:%d; RSP:%s\n", (char*)cmd, rsp_code, (char* )mbtk_ftp_ssl_read_buf); | 
 |             char *mbtk_ftp_ssl_read_buf_p = NULL; | 
 |             mbtk_ftp_ssl_read_buf_p = strstr(mbtk_ftp_ssl_read_buf,"\n"); | 
 |             if(mbtk_ftp_ssl_read_buf_p!=NULL); | 
 |             { | 
 |                 if(strlen(mbtk_ftp_ssl_read_buf_p)>1) | 
 |                 { | 
 |                     mbtk_ftp_ssl_read_buf_p++; | 
 |                     rsp_code = atoi(mbtk_ftp_ssl_read_buf_p); | 
 |                 } | 
 |             } | 
 |             if (rsp_code == 0) | 
 |             { | 
 |                 goto read_angin_2; | 
 |             } | 
 |             return rsp_code; | 
 |         } | 
 |         else | 
 |         { | 
 |             len = sock_readline(&info->net_info, &info->sock_info[FTP_SOCK_CTRL], buff, 1024, FTP_TIMEOUT, | 
 |                             &err); | 
 |         } | 
 |         if (len <= 0) | 
 |         { | 
 |             LOGE("Socket read fail[len = %d].", len); | 
 |             return -1; | 
 |         } | 
 |  | 
 |         rsp_code = atoi(buff); | 
 |         LOGI("%s -> Code:%d; RSP:%s", (char*)cmd, rsp_code, buff); | 
 |         //log_hex("FTP_RSP",buff,len); | 
 |  | 
 |         if (rsp_code == 0) | 
 |         { | 
 |             goto read_angin_2; | 
 |         } | 
 |     } | 
 |  | 
 |     return rsp_code; | 
 | } | 
 |  | 
 | // Create data socket service and waitting client connect. | 
 | static mbtk_ftp_error_enum ftp_data_sock_service_create(mbtk_ftp_sock_s *sock) | 
 | { | 
 |     return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 | static bool ftp_internal_ipv4_check(void *ipv4) | 
 | { | 
 |     char *ip = (char*) ipv4; | 
 |     int ip1 = atoi(ip); | 
 |     ip = strstr(ip, "."); | 
 |     if (!ip) | 
 |         return FALSE; | 
 |     int ip2 = atoi(ip + 1); | 
 |  | 
 |     if (ip1 == 10)   // 10.x.x.x | 
 |     { | 
 |         return TRUE; | 
 |     } | 
 |     else if (ip1 == 172 && (ip2 >= 16 && ip2 <= 31))     // 172.16.0.0 ~ 172.31.255.255 | 
 |     { | 
 |         return TRUE; | 
 |     } | 
 |     else if (ip1 == 192 && ip2 == 168)     // 192.168.x.x | 
 |     { | 
 |         return TRUE; | 
 |     } | 
 |     else | 
 |     { | 
 |         return FALSE; | 
 |     } | 
 | } | 
 |  | 
 | static mbtk_ftp_error_enum ftp_sock_set_by_port(mbtk_ftp_info_s *info, | 
 |         mbtk_ftp_sock_s *sock) | 
 | { | 
 |     // port = port1 * 256 + port2 | 
 |     // "PORT ip1,ip2,ip3,ip4,port1,port2\r\n" | 
 |     int code; | 
 |     char cmd_buff[100]; | 
 |     memset(cmd_buff, 0x0, 100); | 
 |     if (info->sock_info[FTP_SOCK_CTRL].addr_family == MBTK_ADDR_IPV6 || sock->port <= 1024 | 
 |         || strlen((char*) sock->host) == 0) | 
 |     { | 
 |         LOGE("FTP params set error."); | 
 |         return FTP_ERR_PARAM_SET; | 
 |     } | 
 |  | 
 |     if (ftp_data_sock_service_create(sock) != FTP_ERR_SUCCESS) | 
 |     { | 
 |         LOGE("FTP data services create fail."); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     uint8 *ptr = sock->host; | 
 |     while (*ptr) | 
 |     { | 
 |         if (*ptr == '.') | 
 |             *ptr = ','; | 
 |         ptr++; | 
 |     } | 
 |     // Waitting client connect. | 
 |     snprintf(cmd_buff, 100, "PORT %s,%d,%d\r\n", sock->host, sock->port / 256, | 
 |              sock->port % 256); | 
 |     code = ftp_cmd_handle(info, cmd_buff, NULL, NULL); | 
 |     if (code / 100 != 2)   // Not 2xx | 
 |     { | 
 |         LOGE("PORT rsp error[code = %d].", code); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 | static mbtk_ftp_error_enum ftp_sock_set_by_eprt(mbtk_ftp_info_s *info, | 
 |         mbtk_ftp_sock_s *sock) | 
 | { | 
 |     int code; | 
 |     char cmd_buff[100]; | 
 |     memset(cmd_buff, 0x0, 100); | 
 |     if (sock->port <= 1024 || strlen((char*) sock->host) == 0) | 
 |     { | 
 |         LOGE("FTP params set error."); | 
 |         return FTP_ERR_PARAM_SET; | 
 |     } | 
 |     if (ftp_data_sock_service_create(sock) != FTP_ERR_SUCCESS) | 
 |     { | 
 |         LOGE("FTP data services create fail."); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     // "EPRT |2|1080::8:800:200C:417A|5282|" | 
 |     if (info->sock_info[FTP_SOCK_CTRL].addr_family == MBTK_ADDR_IPV6) | 
 |     { | 
 |         uint8 *ptr = NULL; | 
 |         if (sock->host[strlen((char*) sock->host) - 1] == ']') | 
 |             sock->host[strlen((char*) sock->host) - 1] = '\0'; | 
 |  | 
 |         if (sock->host[0] == '[') | 
 |             ptr = sock->host + 1; | 
 |         else | 
 |             ptr = sock->host; | 
 |         snprintf(cmd_buff, 100, "EPRT |2|%s|%d|\r\n", ptr, sock->port); | 
 |     } | 
 |     else       // IPV4 "EPRT |1|132.235.1.2|6275|" | 
 |     { | 
 |         snprintf(cmd_buff, 100, "EPRT |1|%s|%d|\r\n", sock->host, sock->port); | 
 |     } | 
 |  | 
 |     code = ftp_cmd_handle(info, cmd_buff, NULL, NULL); | 
 |     if (code / 100 != 2)   // Not 2xx | 
 |     { | 
 |         LOGE("PORT rsp error[code = %d].", code); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 | static mbtk_ftp_error_enum ftp_sock_get_by_pasv(mbtk_ftp_info_s *info, | 
 |         mbtk_ftp_sock_s *sock) | 
 | { | 
 |     int code; | 
 |     uint8 rsp[1024]; | 
 |     uint32 rsp_len = 1024; | 
 |     memset(sock, 0x0, sizeof(mbtk_ftp_sock_s)); | 
 |     code = ftp_cmd_handle(info, "PASV\r\n", rsp, &rsp_len); | 
 |     /* Found reply-strings include: | 
 |      * "227 Entering Passive Mode (127,0,0,1,4,51)" | 
 |      * "227 Data transfer will passively listen to 127,0,0,1,4,51" | 
 |      * "227 Entering passive mode. 127,0,0,1,4,51" | 
 |      */ | 
 |     if (code != 227) | 
 |     { | 
 |         LOGE("PASV rsp error[code = %d].", code); | 
 |         if(code == 421) | 
 |         { | 
 |             printf("\n code:%d\n",code); | 
 |             return FTP_ERR_UNKNOWN+1; | 
 |         } | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     // Get IPv4 and port | 
 |     uint8 *ptr = rsp + 4; | 
 |     while (*ptr) | 
 |     { | 
 |         if (isdigit(*ptr)) | 
 |             break; | 
 |         ptr++; | 
 |     } | 
 |     // ptr point to first digit. | 
 |     memcpy(sock->host, ptr, strlen((char*) ptr)); | 
 |     ptr = sock->host; | 
 |     int count = 0; | 
 |     while (*ptr) | 
 |     { | 
 |         if (*ptr == ',') | 
 |         { | 
 |             *ptr = '.'; | 
 |             count++; | 
 |         } | 
 |         if (count == 4) | 
 |         { | 
 |             *ptr = '\0'; | 
 |             break; | 
 |         } | 
 |         ptr++; | 
 |     } | 
 |     ptr++; | 
 |  | 
 |     // ptr point to first port digit. | 
 |     int port1 = atoi((char*) ptr); | 
 |     while (*ptr) | 
 |     { | 
 |         if (*ptr == ',') | 
 |             break; | 
 |         ptr++; | 
 |     } | 
 |     ptr++; | 
 |  | 
 |     // ptr point to second port digit. | 
 |     int port2 = atoi((char*) ptr); | 
 |     sock->port = port1 * 256 + port2; | 
 |  | 
 |     LOGI("PASV: %s:%d", sock->host, sock->port); | 
 |  | 
 |     if(ftp_internal_ipv4_check(sock->host)) | 
 |     { | 
 |         memset(sock->host,0x0,MBTK_FTP_IP_MAX + 1); | 
 |         memcpy(sock->host,info->sock_info[FTP_SOCK_CTRL].host,strlen(info->sock_info[FTP_SOCK_CTRL].host)); | 
 |         LOGI("This is internal ipv4,so use IP - %s:%d",sock->host, sock->port); | 
 |     } | 
 |  | 
 |     return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 | static mbtk_ftp_error_enum ftp_sock_get_by_epsv(mbtk_ftp_info_s *info, | 
 |         mbtk_ftp_sock_s *sock) | 
 | { | 
 |     int code; | 
 |     char rsp[1024]; | 
 |     uint32 rsp_len = 1024; | 
 |     memset(sock, 0x0, sizeof(mbtk_ftp_sock_s)); | 
 |     // |||6446| | 
 |     code = ftp_cmd_handle(info, "EPSV\r\n", rsp, &rsp_len); | 
 |     if (code != 229) | 
 |     { | 
 |         LOGE("EPSV rsp error[code = %d].", code); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     /* positive EPSV response */ | 
 |     char *ptr = strchr(rsp, '('); | 
 |     if (ptr) | 
 |     { | 
 |         unsigned int num; | 
 |         char separator[4]; | 
 |         ptr++; | 
 |         if (5 | 
 |             == sscanf(ptr, "%c%c%c%u%c", &separator[0], &separator[1], | 
 |                       &separator[2], &num, &separator[3])) | 
 |         { | 
 |             const char sep1 = separator[0]; | 
 |             int i; | 
 |  | 
 |             /* The four separators should be identical, or else this is an oddly | 
 |              formatted reply and we bail out immediately. */ | 
 |             for (i = 1; i < 4; i++) | 
 |             { | 
 |                 if (separator[i] != sep1) | 
 |                 { | 
 |                     ptr = NULL; /* set to NULL to signal error */ | 
 |                     break; | 
 |                 } | 
 |             } | 
 |             if (num > 0xffff) | 
 |             { | 
 |                 LOGE("Illegal port number in EPSV reply"); | 
 |                 return FTP_ERR_UNKNOWN; | 
 |             } | 
 |             if (ptr) | 
 |             { | 
 |                 sock->port = (uint32) (num & 0xffff); | 
 |                 memcpy(sock->host, info->sock_info[FTP_SOCK_CTRL].host, | 
 |                        strlen(info->sock_info[FTP_SOCK_CTRL].host)); | 
 |             } | 
 |         } | 
 |         else | 
 |         { | 
 |             ptr = NULL; | 
 |         } | 
 |     } | 
 |     if (!ptr) | 
 |     { | 
 |         LOGE("Weirdly formatted EPSV reply"); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     LOGI("PASV: %s:%d", sock->host, sock->port); | 
 |  | 
 |     return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 | /* | 
 |  * 04-26-20  02:13PM               379193 audio_0426.zip | 
 |  * 09-10-20  02:31PM              4660645 Log.zip | 
 |  * 10-28-20  01:53PM       <DIR>          PicLibs | 
 |  */ | 
 |  | 
 |  /* | 
 |  *-rw-r--r-- 1 ftp ftp     2097152000 Feb 18 17:28 ASR1803_Linux.tar.gz_aa | 
 |  *-rw-r--r-- 1 ftp ftp     2097152000 Feb 18 17:21 ASR1803_Linux.tar.gz_ab | 
 |  *-rw-r--r-- 1 ftp ftp     1198057917 Feb 18 17:29 ASR1803_Linux.tar.gz_ac | 
 |  *-rw-r--r-- 1 ftp ftp         445043 Apr 06  2021 data | 
 |  *drwxr-xr-x 1 ftp ftp              0 Apr 10  2021 L306 | 
 |  */ | 
 | static mbtk_ftp_error_enum ftp_cmd_list_parse(mbtk_ftp_info_s *info, | 
 |         mbtk_ftp_file_info_s *file_list) | 
 | { | 
 |     char line[1024]; | 
 |     char line_buf[1024]; | 
 |     int len, err; | 
 |     mbtk_ftp_file_info_s file_ptr; | 
 |     memset(file_list, 0x0, sizeof(mbtk_ftp_file_info_s)-sizeof(void *)); | 
 |  | 
 |     // Save file number. | 
 |     file_list->size = 0; | 
 |     len = 1; | 
 |     int read_line_count=0; | 
 |     while (len > 0) | 
 |     { | 
 |         if(info->auth_type!=0) | 
 |         { | 
 |             len = mbtk_sock_readline(info->ftp_ssl_handle,info->session_data,line_buf,1024,FTP_TIMEOUT,&err,&read_line_count,line); | 
 |         } | 
 |         else | 
 |         { | 
 |             len = sock_readline(&info->net_info, &info->sock_info[FTP_SOCK_DATA], line, 1024,FTP_TIMEOUT, &err); | 
 |         } | 
 |         LOGD("Line:%s", line); | 
 |         if(len <= 0) | 
 |             { | 
 |                 if (err == MBTK_SOCK_SUCCESS) | 
 |                     return FTP_ERR_SUCCESS; | 
 |                 break; | 
 |             } | 
 |         else | 
 |             len = strlen(line) - 1; | 
 |         if (line[0] >= '0' && line[0] <= '9') | 
 |         { | 
 |             /* | 
 |              * 04-26-20  02:13PM               379193 audio_0426.zip | 
 |              * 09-10-20  02:31PM              4660645 Log.zip | 
 |              * 10-28-20  01:53PM       <DIR>          PicLibs | 
 |              */ | 
 |             line[len] = '\0'; | 
 |             /* | 
 |             file_ptr = (mbtk_ftp_file_info_s*) malloc( | 
 |                            sizeof(mbtk_ftp_file_info_s)); | 
 |             if (!file_ptr) | 
 |             { | 
 |                 LOGE("malloc() fail."); | 
 |                 return FTP_ERR_UNKNOWN; | 
 |             } | 
 |             */ | 
 |             memset(&file_ptr, 0x0, sizeof(mbtk_ftp_file_info_s)); | 
 |  | 
 |             char str[MBTK_FTP_FILE_NAME_MAX]; | 
 |             const char *temp = line; | 
 |             // Data | 
 |             temp = ftp_str_next(temp, str, MBTK_FTP_FILE_NAME_MAX); | 
 |             if (strlen(str) > 0) | 
 |             { | 
 |                 LOGV("Data:%s", str); | 
 |             } | 
 |  | 
 |             // Time | 
 |             temp = ftp_str_next(temp, str, MBTK_FTP_FILE_NAME_MAX); | 
 |             if (strlen(str) > 0) | 
 |             { | 
 |                 LOGV("Time:%s", str); | 
 |             } | 
 |  | 
 |             // <DIR> or file size | 
 |             temp = ftp_str_next(temp, str, MBTK_FTP_FILE_NAME_MAX); | 
 |             if (strlen(str) > 0) | 
 |             { | 
 |                 LOGV("<DIR>/size:%s", str); | 
 |                 if (!strcmp("<DIR>", str)) | 
 |                 { | 
 |                     file_ptr.is_file = false; | 
 |                     file_ptr.size = 0; | 
 |                 } | 
 |                 else | 
 |                 { | 
 |                     file_ptr.is_file = true; | 
 |                     file_ptr.size = atoi(str); | 
 |                 } | 
 |             } | 
 |  | 
 |             const char *name = temp; | 
 |             while (*name && ftp_ch_is_space(*name)) | 
 |             { | 
 |                 name++; | 
 |             } | 
 |  | 
 |             // Name | 
 |             if (strlen(name) > 0) | 
 |             { | 
 |                 LOGV("Name:%s",name); | 
 |                 memset(file_ptr.name,0,strlen(file_ptr.name)+1); | 
 |                 memcpy(file_ptr.name, name, strlen(name)); | 
 |                 char *temp = (char*) file_ptr.name | 
 |                              + strlen((char*) file_ptr.name) - 1; | 
 |                 while (ftp_ch_is_space(*temp)) | 
 |                 { | 
 |                     *temp = '\0'; | 
 |                     temp--; | 
 |                 } | 
 |             } | 
 |             else | 
 |             { | 
 |                 LOGE("Can not get name[%s].", line); | 
 |                 return FTP_ERR_UNKNOWN; | 
 |             } | 
 |  | 
 |             (file_list->ftp_ls_cb_typedef)(&file_ptr); | 
 |             //file_ptr->next = file_list->next; | 
 |             //file_list->next = file_ptr; | 
 |             //file_list->size++; | 
 |             //free(file_ptr); | 
 |         } else if(!ftp_ch_is_space(line[0])) { | 
 |              /* | 
 |              *-rw-r--r-- 1 ftp ftp     2097152000 Feb 18 17:28 ASR1803_Linux.tar.gz_aa | 
 |              *-rw-r--r-- 1 ftp ftp     2097152000 Feb 18 17:21 ASR1803_Linux.tar.gz_ab | 
 |              *-rw-r--r-- 1 ftp ftp     1198057917 Feb 18 17:29 ASR1803_Linux.tar.gz_ac | 
 |              *-rw-r--r-- 1 ftp ftp         445043 Apr 06  2021 data | 
 |              *drwxr-xr-x 1 ftp ftp              0 Apr 10  2021 L306 | 
 |              */ | 
 |             line[len] = '\0'; | 
 |              /* | 
 |             file_ptr = (mbtk_ftp_file_info_s*) malloc( | 
 |                            sizeof(mbtk_ftp_file_info_s)); | 
 |             if (!file_ptr) | 
 |             { | 
 |                 LOGE("malloc() fail."); | 
 |                 return FTP_ERR_UNKNOWN; | 
 |             } | 
 |             */ | 
 |             memset(&file_ptr, 0x0, sizeof(mbtk_ftp_file_info_s)); | 
 |  | 
 |             char str[MBTK_FTP_FILE_NAME_MAX]; | 
 |             const char *temp = line; | 
 |             // rwx | 
 |             temp = ftp_str_next(temp, str, MBTK_FTP_FILE_NAME_MAX); | 
 |             if (strlen(str) > 0) | 
 |             { | 
 |                 LOGV("rwx:%s", str); | 
 |                 file_ptr.is_file = (str[0] == '-' ? true : false); | 
 |             } | 
 |  | 
 |             // 1 ftp ftp | 
 |             temp = ftp_str_next(temp, str, MBTK_FTP_FILE_NAME_MAX); | 
 |             temp = ftp_str_next(temp, str, MBTK_FTP_FILE_NAME_MAX); | 
 |             temp = ftp_str_next(temp, str, MBTK_FTP_FILE_NAME_MAX); | 
 |  | 
 |             // size | 
 |             temp = ftp_str_next(temp, str, MBTK_FTP_FILE_NAME_MAX); | 
 |             if (strlen(str) > 0) | 
 |             { | 
 |                 LOGV("Size:%s", str); | 
 |                 file_ptr.size = atoi(str); | 
 |             } | 
 |  | 
 |             // Feb 18 17:28 | 
 |             // or | 
 |             // Apr 10  2021 | 
 |             temp = ftp_str_next(temp, str, MBTK_FTP_FILE_NAME_MAX); | 
 |             temp = ftp_str_next(temp, str, MBTK_FTP_FILE_NAME_MAX); | 
 |             temp = ftp_str_next(temp, str, MBTK_FTP_FILE_NAME_MAX); | 
 |  | 
 |             const char *name = temp; | 
 |             while (*name && ftp_ch_is_space(*name)) | 
 |             { | 
 |                 name++; | 
 |             } | 
 |  | 
 |             // Name | 
 |             if (strlen(name) > 0) | 
 |             { | 
 |                 LOGV("Name:%s",name); | 
 |                 memset(file_ptr.name,0,strlen(file_ptr.name)+1); | 
 |                 memcpy(file_ptr.name, name, strlen(name)); | 
 |                 char *temp = (char*) file_ptr.name | 
 |                              + strlen((char*) file_ptr.name) - 1; | 
 |                 while (ftp_ch_is_space(*temp)) | 
 |                 { | 
 |                     *temp = '\0'; | 
 |                     temp--; | 
 |                 } | 
 |             } | 
 |             else | 
 |             { | 
 |                 LOGE("Can not get name[%s].", line); | 
 |                 return FTP_ERR_UNKNOWN; | 
 |             } | 
 |  | 
 |             (file_list->ftp_ls_cb_typedef)(&file_ptr); | 
 |             //file_ptr->next = file_list->next; | 
 |             //file_list->next = file_ptr; | 
 |             //file_list->size++; | 
 |             //free(file_ptr); | 
 |         }else { | 
 |             LOGE("Data error."); | 
 |             return FTP_ERR_UNKNOWN; | 
 |         } | 
 |     } | 
 |     return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 | static mbtk_ftp_error_enum ftp_download_process(mbtk_ftp_info_s *info) | 
 | { | 
 | #define READ_BUF_SIZE 2048 | 
 |     char buff[READ_BUF_SIZE]; | 
 |     int len, err, len_read; | 
 |     int read_count = info->file_trans.size_send; | 
 |  | 
 | #ifdef FTP_RESUME_DEBUG | 
 |     int count = 0; | 
 | #endif | 
 |  | 
 |     if (info->file_trans.size_count - read_count > READ_BUF_SIZE) | 
 |         len_read = READ_BUF_SIZE; | 
 |     else | 
 |         len_read = info->file_trans.size_count - read_count; | 
 |  | 
 |     if(info->auth_type != 0) | 
 |         len = mbtk_sock_read(info->ftp_ssl_handle,info->session_data,buff,len_read,FTP_TIMEOUT,&err); | 
 |     else | 
 |         len = sock_read(&info->net_info, &info->sock_info[FTP_SOCK_DATA], buff, len_read,FTP_TIMEOUT, &err); | 
 |     /* | 
 |     while (len_read > 0 && (len = sock_read(&info->net_info, &info->sock_info[FTP_SOCK_DATA], buff, len_read, | 
 |                                     FTP_TIMEOUT, &err)) > 0) | 
 |     */ | 
 |     while (len_read > 0 && len > 0) | 
 |     { | 
 |         read_count += len; | 
 |  | 
 | #ifdef FTP_RESUME_DEBUG | 
 |         count++; | 
 |         if (count <= 1000) | 
 |         { | 
 | #endif | 
 |             if (info->file_trans.data_cb) | 
 |             { | 
 |                 info->file_trans.data_cb(buff, len); | 
 |             } | 
 |             else     // Write to efs. | 
 |             { | 
 |                 if (len != file_write(info->file_trans.fd, buff, len)) | 
 |                 { | 
 |                     LOGE("EFS write fail."); | 
 |                     return FTP_ERR_EFS_FILE; | 
 |                 } | 
 |             } | 
 |             memset(buff,0,sizeof(buff)); | 
 |             info->file_trans.size_send = read_count; | 
 | #ifdef FTP_RESUME_DEBUG | 
 |         } | 
 | #endif | 
 |  | 
 |         if (info->file_trans.size_count - read_count > READ_BUF_SIZE) | 
 |             len_read = READ_BUF_SIZE; | 
 |         else | 
 |             len_read = info->file_trans.size_count - read_count; | 
 |  | 
 |         if(info->auth_type != 0) | 
 |             len = mbtk_sock_read(info->ftp_ssl_handle,info->session_data,buff,len_read,FTP_TIMEOUT,&err); | 
 |         else | 
 |             len = sock_read(&info->net_info, &info->sock_info[FTP_SOCK_DATA], buff, len_read,FTP_TIMEOUT, &err); | 
 |     } | 
 |  | 
 |     return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 | static mbtk_ftp_error_enum ftp_update_process(mbtk_ftp_info_s *info) | 
 | { | 
 | #define READ_BUF_SIZE 2048 | 
 |     char buff[READ_BUF_SIZE]; | 
 |     int len, err, len_write; | 
 | 	int file_total_size = 0; | 
 |     int write_count = 0; | 
 |  | 
 | 	if(info->file_trans.fd > 0) | 
 | 	{ | 
 | 		file_total_size = file_length(info->file_trans.fd); | 
 |         info->file_trans.size_count = file_total_size; | 
 | 		while((len_write = file_read(info->file_trans.fd, buff, READ_BUF_SIZE)) > 0 ) | 
 | 		{ | 
 | 			LOGE("file_read.len:%d, buf;%s", len_write, buff); | 
 |             if(info->auth_type != 0) | 
 |                 len = mbtk_sock_write(info->ftp_ssl_handle,info->session_data,buff,len_write,FTP_TIMEOUT,&err); | 
 |             else | 
 | 			    len = sock_write(&info->net_info, &info->sock_info[FTP_SOCK_DATA], buff, len_write, | 
 |                                     FTP_TIMEOUT, &err); | 
 | 			if(len < 0) | 
 | 			{ | 
 | 				LOGE("EFS write fail.len:%d, err;%d", len, err); | 
 |                 return FTP_ERR_EFS_FILE; | 
 | 			} | 
 |  | 
 | 			write_count += len; | 
 | 		} | 
 |  | 
 |         info->file_trans.size_send = write_count; | 
 | 		if( write_count != file_total_size) | 
 | 		{ | 
 | 			LOGE("socket write fail.,file_total_size:%d, write_count:%d", file_total_size,write_count); | 
 |             return FTP_ERR_NET_WRITE; | 
 | 		} | 
 | 		else{ | 
 | 			LOGE("socket write success.,file_total_size:%d, write_count:%d", file_total_size, write_count); | 
 | 		} | 
 |  | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		LOGE("EFS write fail."); | 
 |         return FTP_ERR_EFS_FILE; | 
 | 	} | 
 |  | 
 | 	return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 |  | 
 | /* | 
 |  * audio_0426.zip | 
 |  * Log.zip | 
 |  * PicLibs | 
 |  */ | 
 | static mbtk_ftp_error_enum ftp_cmd_nlst_parse(mbtk_ftp_info_s *info, | 
 |         mbtk_ftp_file_info_s *file_list) | 
 | { | 
 |     char line[1024]; | 
 |     int len, err; | 
 |     mbtk_ftp_file_info_s *file_ptr = NULL; | 
 |     while ((len = sock_readline(&info->net_info, &info->sock_info[FTP_SOCK_DATA], line, 1024, | 
 |                                 FTP_TIMEOUT, &err)) > 0) | 
 |     { | 
 |         if (!ftp_ch_is_space(line[0])) | 
 |         { | 
 |             file_ptr = (mbtk_ftp_file_info_s*) malloc( | 
 |                            sizeof(mbtk_ftp_file_info_s)); | 
 |             if (!file_ptr) | 
 |             { | 
 |                 LOGE("malloc() fail."); | 
 |                 return FTP_ERR_UNKNOWN; | 
 |             } | 
 |             memset(file_ptr, 0x0, sizeof(mbtk_ftp_file_info_s)); | 
 |             memcpy(file_ptr->name, line, strlen(line)); | 
 |             char *temp = (char*) file_ptr->name + strlen((char*) file_ptr->name) | 
 |                          - 1; | 
 |             while (ftp_ch_is_space(*temp)) | 
 |             { | 
 |                 *temp = '\0'; | 
 |                 temp--; | 
 |             } | 
 |  | 
 |             file_ptr->next = file_list->next; | 
 |             file_list->next = file_ptr; | 
 |         } | 
 |     } | 
 |     return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 | static mbtk_ftp_error_enum ftp_data_sock_read(mbtk_ftp_info_s *info, | 
 |         mbtk_ftp_cmd_enum cmd, void *req, void *rsp) | 
 | { | 
 |     int err, len, code; | 
 |     mbtk_ftp_error_enum result = FTP_ERR_SUCCESS; | 
 |     char buff[1024]; | 
 |     if (info->is_data_sock_busy) | 
 |     { | 
 |         LOGW("Data socket is busy!"); | 
 |         return FTP_ERR_DATA_SOCK_BUSY; | 
 |     } | 
 |  | 
 |     info->is_data_sock_busy = true; | 
 |     // Connect to service by data socket. | 
 |     if (info->data_mode == FTP_MODE_PASSIVE) | 
 |     { | 
 |         mbtk_ftp_sock_s sock; | 
 |         if(info->auth_type != FTP_AUTH_TYPE_NON) { | 
 |             // PROT P | 
 |             char cmd_ssl[50]; | 
 |             memset(cmd_ssl,0,50); | 
 |             snprintf(cmd_ssl, 50, "PROT P\r\n"); | 
 |             code = ftp_cmd_handle(info, cmd_ssl, NULL,NULL); | 
 |             if (code/100 != 2) | 
 |             { | 
 |                 LOGE("PROT P error[code = %d].", code); | 
 |                 goto end; | 
 |             } | 
 |         } | 
 |  | 
 |         if (info->sock_info[FTP_SOCK_CTRL].addr_family == MBTK_ADDR_IPV6) | 
 |         { | 
 |             if ((result = ftp_sock_get_by_epsv(info, &sock)) | 
 |                 != FTP_ERR_SUCCESS) | 
 |             { | 
 |                 goto end; | 
 |             } | 
 |         } | 
 |         else | 
 |         { | 
 |             if ((result = ftp_sock_get_by_pasv(info, &sock)) | 
 |                 != FTP_ERR_SUCCESS) | 
 |             { | 
 |                 printf("\nftp_sock_get_by_pasv end.result=%d\n",result); | 
 |             } | 
 |             else | 
 |             { | 
 |                 printf("\nftp_sock_get_by_pasv ok!\n"); | 
 |             } | 
 |         } | 
 |  | 
 |         if(info->auth_type != FTP_AUTH_TYPE_NON) | 
 |         { | 
 |             info->ftp_ssl_handle_data = mbtk_sock_init(&info->ftp_ssl_info_data); | 
 |             if(info->ftp_ssl_handle_data == -1) | 
 |             { | 
 |                 printf("mbtk_sock_init error\n"); | 
 |             } | 
 |             info->ftp_sock_ssl_info_data = (mbtk_sock_info*) malloc(sizeof(mbtk_sock_info)); | 
 |             memset(info->ftp_sock_ssl_info_data, 0x0, sizeof(mbtk_sock_info)); | 
 |             info->ftp_sock_ssl_info_data->is_support_ssl = info->auth_type; | 
 |             info->ftp_sock_ssl_info_data->ftp_ssl_support=1; | 
 |             info->ftp_sock_ssl_info_data->port = sock.port; | 
 |             info->ftp_sock_ssl_info_data->type = MBTK_SOCK_TCP; | 
 |             info->ftp_sock_ssl_info_data->ingnore_cert = ~(info->sock_info[FTP_SOCK_CTRL].use_cert); | 
 |             memcpy(info->ftp_sock_ssl_info_data->address, sock.host, strlen(sock.host)); | 
 |             if(info->ftp_sock_ssl_info_data->is_support_ssl != 0) | 
 |             { | 
 |                 info->ftp_sock_ssl_info_data->is_support_ssl = 0; | 
 |             } | 
 |             info->session_data = mbtk_sock_open(info->ftp_ssl_handle,info->ftp_sock_ssl_info_data,60000,&err); | 
 |             if(err!=0) | 
 |             { | 
 |                 printf("mbtk_sock_open error : %d\n",err); | 
 |             } | 
 |             else | 
 |             { | 
 |                 info->ftp_sock_ssl_info_data->is_support_ssl = info->auth_type; | 
 |                 //printf("\ninfo->session_data = %d \n",info->session_data); | 
 |             } | 
 |         } | 
 |         else | 
 |         { | 
 |             memcpy(info->sock_info[FTP_SOCK_DATA].host, sock.host, strlen((char*)sock.host)); | 
 |             info->sock_info[FTP_SOCK_DATA].port = sock.port; | 
 |             info->sock_info[FTP_SOCK_DATA].is_ssl = (info->auth_type != FTP_AUTH_TYPE_NON); | 
 |             info->sock_info[FTP_SOCK_DATA].addr_family = info->sock_info[FTP_SOCK_CTRL].addr_family; | 
 |             info->sock_info[FTP_SOCK_DATA].use_cert = info->sock_info[FTP_SOCK_CTRL].use_cert; | 
 |             info->net_info.keep_alive = FALSE; | 
 |             info->net_info.recv_buff_size = 32 * 1024; // 32K | 
 |             info->sock_info[FTP_SOCK_DATA].fd = sock_open(&info->net_info, &info->sock_info[FTP_SOCK_DATA], | 
 |                                                     FTP_TIMEOUT, &err); | 
 |         } | 
 |  | 
 |     } | 
 |     else    // Active mode | 
 |     { | 
 |         if (req == NULL) | 
 |         { | 
 |             result = FTP_ERR_PARAM_SET; | 
 |             goto end; | 
 |         } | 
 |         mbtk_ftp_sock_s *sock = (mbtk_ftp_sock_s*) req; | 
 |  | 
 |         if (info->sock_info[FTP_SOCK_CTRL].addr_family == MBTK_ADDR_IPV6) | 
 |         { | 
 |             if ((result = ftp_sock_set_by_eprt(info, sock)) | 
 |                 != FTP_ERR_SUCCESS) | 
 |             { | 
 |                 goto end; | 
 |             } | 
 |         } | 
 |         else | 
 |         { | 
 |             if ((result = ftp_sock_set_by_port(info, sock)) | 
 |                 != FTP_ERR_SUCCESS) | 
 |             { | 
 |                 goto end; | 
 |             } | 
 |         } | 
 |  | 
 |         // Wait for client[service] connect. | 
 |  | 
 |     } | 
 |     if(info->auth_type != FTP_AUTH_TYPE_NON) | 
 |     { | 
 |         if(info->session_data < 0) | 
 |         { | 
 |                //printf("Socket open/connect ssl fail[err = %d].", err); | 
 |                result = FTP_ERR_NET_CONN; | 
 |                goto read_end; | 
 |         } | 
 |     } | 
 |     else | 
 |     { | 
 |         if (info->sock_info[FTP_SOCK_DATA].fd < 0) | 
 |         { | 
 |             LOGE("Socket open/connect fail[err = %d].", err); | 
 |             result = FTP_ERR_NET_CONN; | 
 |             goto read_end; | 
 |         } | 
 |  | 
 |         if(info->auth_type == FTP_AUTH_TYPE_IMPLICIT) { | 
 |             info->sock_info[FTP_SOCK_DATA].is_ssl = true; | 
 |         } | 
 |     } | 
 |  | 
 |     if (cmd == FTP_CMD_GET)   // Is download | 
 |     { | 
 |         char cmd[100]; | 
 |         if (info->file_trans.size_send > 0)   // Resume transmission | 
 |         { | 
 |             // REST size | 
 |             memset(cmd, 0x0, 100); | 
 |             snprintf(cmd, 100, "REST %ld\r\n", info->file_trans.size_send); | 
 |             code = ftp_cmd_handle(info, cmd, NULL, NULL); | 
 |             if (code != 350) | 
 |             { | 
 |                 LOGE("REST rsp error[code = %d].", code); | 
 |                 result = FTP_ERR_UNKNOWN; | 
 |                 goto end; | 
 |             } | 
 |         } | 
 |  | 
 |         memset(cmd, 0x0, 100); | 
 |         snprintf(cmd, 100, "RETR %s\r\n", info->file_trans.remote_name); | 
 |         code = ftp_cmd_handle(info, cmd, NULL, NULL); | 
 |         if (code != 125 && code != 150) | 
 |         { | 
 |             LOGE("RETR %s rsp error[code = %d].", info->file_trans.remote_name, | 
 |                  code); | 
 |             result = FTP_ERR_UNKNOWN; | 
 |             goto end; | 
 |         } | 
 |  | 
 |         int mbtk_errno; | 
 |         if(info->auth_type != 0) | 
 |         { | 
 |             mbtk_errno = mbtk_ssl_init_func(info->ftp_ssl_handle,info->ftp_sock_ssl_info_data->ingnore_cert,info->session_data); | 
 |             if(mbtk_errno != 0) | 
 |             { | 
 |                 printf("\nmbtk_ssl_init_func error = %d",mbtk_errno); | 
 |                 goto end; | 
 |             } | 
 |  | 
 |         } | 
 |         result = ftp_download_process(info); | 
 |         if(info->auth_type != 0) | 
 |         { | 
 |             char mbtk_ftp_ssl_read_buf[256]; | 
 |             memset(mbtk_ftp_ssl_read_buf,0,sizeof(mbtk_ftp_ssl_read_buf)); | 
 |             mbtk_sock_read(info->ftp_ssl_handle,info->session, | 
 |                                        mbtk_ftp_ssl_read_buf, | 
 |                                        sizeof(mbtk_ftp_ssl_read_buf), | 
 |                                        6000, | 
 |                                        &mbtk_errno); | 
 |             printf("\nmbtk_sock_read:\n%s\n",mbtk_ftp_ssl_read_buf); | 
 |         } | 
 |         if(info->auth_type != 0) | 
 |             goto read_end; | 
 |     } | 
 | 	else if (cmd == FTP_CMD_PUT)   // Is download | 
 |     { | 
 |         if(info->auth_type != 0) | 
 |         { | 
 |                 int mbtk_errno; | 
 |                 char cmd[100]; | 
 |                 memset(cmd, 0x0, 100); | 
 |                 snprintf(cmd, 100, "STOR %s\r\n", info->file_trans.remote_name); | 
 |         		LOGE("STOR %s .name:%s ", cmd, info->file_trans.remote_name); | 
 |                 code = ftp_cmd_handle(info, cmd, NULL, NULL); | 
 |                 if (code != 125 && code != 150) | 
 |                 { | 
 |                     LOGE("RETR %s rsp error[code = %d].", info->file_trans.remote_name, | 
 |                          code); | 
 |                     //printf("RETR %s rsp error[code = %d].\n", info->file_trans.remote_name,code); | 
 |                     result = FTP_ERR_UNKNOWN; | 
 |                     goto end; | 
 |                 } | 
 |  | 
 |                 mbtk_errno = mbtk_ssl_init_func(info->ftp_ssl_handle,info->ftp_sock_ssl_info_data->ingnore_cert,info->session_data); | 
 |                 if(mbtk_errno != 0) | 
 |                 { | 
 |                     printf("\nmbtk_ssl_init_func error = %d",mbtk_errno); | 
 |                     goto end; | 
 |                 } | 
 |                 if(info->file_trans.size_count == 0) | 
 |             	{ | 
 |             	    result = ftp_update_process(info); | 
 |             	    goto read_end; | 
 |             	} | 
 |             	else | 
 |             	{ | 
 |                     //printf("FTP_SOCK_DATA,fd:%d\n",info->file_trans.size_count); | 
 |             	    return FTP_ERR_SUCCESS; | 
 |             	} | 
 |             goto end; | 
 |         } | 
 |         else | 
 |         { | 
 |             char cmd[100]; | 
 |             memset(cmd, 0x0, 100); | 
 |             snprintf(cmd, 100, "STOR %s\r\n", info->file_trans.remote_name); | 
 |     		LOGE("STOR %s .name:%s ", cmd, info->file_trans.remote_name); | 
 |             code = ftp_cmd_handle(info, cmd, NULL, NULL); | 
 |             if (code != 125 && code != 150) | 
 |             { | 
 |                 LOGE("RETR %s rsp error[code = %d].", info->file_trans.remote_name, | 
 |                      code); | 
 |                 result = FTP_ERR_UNKNOWN; | 
 |                 goto end; | 
 |             } | 
 |  | 
 |         	if(info->file_trans.size_count == 0) | 
 |         	{ | 
 |         	    result = ftp_update_process(info); | 
 |         	    goto read_end; | 
 |         	} | 
 |         	else | 
 |         	{ | 
 |                     LOGE("FTP_SOCK_DATA,fd:%d", info->sock_info[FTP_SOCK_DATA].fd); | 
 |         	    return FTP_ERR_SUCCESS; | 
 |         	} | 
 |         } | 
 |     } | 
 |     else if (cmd == FTP_CMD_LIST) | 
 |     { | 
 |         if(info->auth_type != 0) | 
 |         { | 
 |         	int mbtk_errno; | 
 |         	code = ftp_cmd_handle(info, "LIST\r\n", NULL, NULL); | 
 |         	if (code != 125 && code != 150) | 
 |             { | 
 |             	LOGE("LIST rsp error[code = %d].", code); | 
 |                 result = FTP_ERR_UNKNOWN; | 
 |                 goto read_end; | 
 |             } | 
 |  | 
 |             mbtk_errno = mbtk_ssl_init_func(info->ftp_ssl_handle,info->ftp_sock_ssl_info_data->ingnore_cert,info->session_data); | 
 |             if(mbtk_errno != 0) | 
 |             { | 
 |             	printf("\nmbtk_ssl_init_func error = %d",mbtk_errno); | 
 |                 goto read_end; | 
 |             } | 
 |  | 
 |             result = ftp_cmd_list_parse(info, (mbtk_ftp_file_info_s*) rsp); | 
 |             char mbtk_ftp_ssl_read_buf[1024]; | 
 |             memset(mbtk_ftp_ssl_read_buf,0,sizeof(mbtk_ftp_ssl_read_buf)); | 
 |             mbtk_sock_read(info->ftp_ssl_handle,info->session, | 
 |                                 mbtk_ftp_ssl_read_buf, | 
 |                                 sizeof(mbtk_ftp_ssl_read_buf), | 
 |                                 6000, | 
 |                                 &mbtk_errno); | 
 |             printf("\nmbtk_sock_read:\n%s\n",mbtk_ftp_ssl_read_buf); | 
 |             int rsp_code = atoi(mbtk_ftp_ssl_read_buf); | 
 |             if(rsp_code / 200) | 
 |             	result = FTP_ERR_SUCCESS; | 
 |             goto read_end; | 
 |         } | 
 |         else | 
 |         { | 
 |             code = ftp_cmd_handle(info, "LIST\r\n", NULL, NULL); | 
 |             if (code != 125 && code != 150) | 
 |             { | 
 |                 LOGE("LIST rsp error[code = %d].", code); | 
 |                 result = FTP_ERR_UNKNOWN; | 
 |                 goto end; | 
 |             } | 
 |  | 
 |             result = ftp_cmd_list_parse(info, (mbtk_ftp_file_info_s*) rsp); | 
 |         } | 
 |     } | 
 |     else if (cmd == FTP_CMD_NLST) | 
 |     { | 
 |         code = ftp_cmd_handle(info, "NLST\r\n", NULL, NULL); | 
 |         if (code != 125 && code != 150) | 
 |         { | 
 |             LOGE("LIST rsp error[code = %d].", code); | 
 |             result = FTP_ERR_UNKNOWN; | 
 |             goto end; | 
 |         } | 
 |  | 
 |         result = ftp_cmd_nlst_parse(info, (mbtk_ftp_file_info_s*) rsp); | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGE("No support this cmd[%d].", cmd); | 
 |         result = FTP_ERR_UNKNOWN; | 
 |         goto read_end; | 
 |     } | 
 |  | 
 |     // Read [226 Transfer complete.] | 
 | read_code: | 
 |     memset(buff, 0x0, 1024); | 
 |     len = sock_readline(&info->net_info, &info->sock_info[FTP_SOCK_CTRL], buff, 1024, FTP_TIMEOUT, | 
 |                     &err); | 
 |     if (len <= 0) | 
 |     { | 
 |         LOGE("Socket read fail[len = %d].", len); | 
 |         result = FTP_ERR_NET_READ; | 
 |         goto sock_error; | 
 |     } | 
 |     LOGI("RSP[len-%d]:%s",len,buff); | 
 |     //log_hex("FTP_RSP",buff,len); | 
 |     code = atoi(buff); | 
 |     if (code == 0) | 
 |     { | 
 |         goto read_code; | 
 |     } | 
 | #if 1 | 
 |     // 426 Connection closed; aborted transfer of "/files/test" | 
 |     else if (code == 426) | 
 |     { | 
 |         LOGE("Connection closed,restart download..."); | 
 |         result = FTP_ERR_UNKNOWN; | 
 |         goto sock_error; | 
 |     } | 
 | #endif | 
 |     else if (code != 226) | 
 |     { | 
 |         LOGE("Code not be 226[%s].", buff); | 
 |         result = FTP_ERR_UNKNOWN; | 
 |         goto read_end; | 
 |     } | 
 |  | 
 |     goto read_end; | 
 | sock_error: | 
 |     { | 
 |         if (info->sock_info[FTP_SOCK_CTRL].fd > 0) | 
 |         { | 
 |             if (sock_close(&info->net_info, &info->sock_info[FTP_SOCK_CTRL], FTP_TIMEOUT, &err)) | 
 |             { | 
 |                 LOGE("Close ctrl socket fail[%d].", err); | 
 |             } | 
 |         } | 
 |         info->state = FTP_STATE_NON; | 
 |         info->sock_info[FTP_SOCK_CTRL].fd = -1; | 
 |     } | 
 | read_end: | 
 |     // Close data socket. | 
 |     if (info->sock_info[FTP_SOCK_DATA].fd > 0) | 
 |     { | 
 |         if (sock_close(&info->net_info, &info->sock_info[FTP_SOCK_DATA], FTP_TIMEOUT, &err)) | 
 |         { | 
 |             LOGE("Close data socket fail[%d].", err); | 
 |             result = FTP_ERR_NET_CLOSE; | 
 |         } | 
 |         else | 
 |         { | 
 |             info->sock_info[FTP_SOCK_DATA].fd = -1; | 
 |         } | 
 |     } | 
 |     if(info->auth_type != 0) | 
 |     { | 
 |         if(mbtk_sock_close(info->ftp_ssl_handle,info->session_data,6000,&err)) | 
 |         { | 
 |             LOGE("Close ssl data socket fail[%d].", err); | 
 |             result = FTP_ERR_NET_CLOSE; | 
 |         } | 
 |         else | 
 |         { | 
 |         //    info->sock_info[FTP_SOCK_DATA].fd = -1; | 
 |         } | 
 |     } | 
 |     if (info->data_mode == FTP_MODE_PASSIVE) | 
 |     { | 
 |  | 
 |     } | 
 |     else | 
 |     { | 
 |  | 
 |     } | 
 |  | 
 | end: | 
 |     // Default is passive. | 
 |     info->data_mode = FTP_MODE_PASSIVE; | 
 |     info->is_data_sock_busy = false; | 
 |  | 
 |     return result; | 
 | } | 
 |  | 
 | static mbtk_ftp_error_enum ftp_cmd_process_pwd(mbtk_ftp_info_s *info, | 
 |         char *path) | 
 | { | 
 |     int code; | 
 |     char rsp[100]; | 
 |     uint32 rsp_len = 100; | 
 |     code = ftp_cmd_handle(info, "PWD\r\n", rsp, &rsp_len); | 
 |     if (code != 257) | 
 |     { | 
 |         LOGE("PWD rsp error[code = %d].", code); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     // "path" is current .... | 
 |     char *ptr = strchr(rsp, '"'); | 
 |     if (!ptr) | 
 |     { | 
 |         LOGE("PWD rsp error[%d].", code); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     ptr++; | 
 |     char *ptr_temp = ptr; | 
 |     while (*ptr_temp) | 
 |     { | 
 |         if (*ptr_temp == '"') | 
 |         { | 
 |             *ptr_temp = '\0'; | 
 |             break; | 
 |         } | 
 |         ptr_temp++; | 
 |     } | 
 |     memcpy(path, ptr, strlen(ptr)); | 
 |     path[strlen(ptr)] = '\0'; | 
 |  | 
 |     return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 | static mbtk_ftp_error_enum ftp_cmd_process_cwd(mbtk_ftp_info_s *info, | 
 |         const char *path) | 
 | { | 
 |     int code; | 
 |     char cmd[100] = { 0 }; | 
 |     snprintf(cmd, 100, "CWD %s\r\n", path); | 
 |     code = ftp_cmd_handle(info, cmd, NULL, NULL); | 
 |     if (code != 250) | 
 |     { | 
 |         LOGE("CWD rsp error[code = %d].", code); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 | static mbtk_ftp_error_enum ftp_cmd_process_mkd(mbtk_ftp_info_s *info, | 
 |         const char *path) | 
 | { | 
 |     int code; | 
 |     char cmd[100] = { 0 }; | 
 |     snprintf(cmd, 100, "MKD %s\r\n", path); | 
 |     code = ftp_cmd_handle(info, cmd, NULL, NULL); | 
 |     if (code == 257) | 
 |     { | 
 |         return FTP_ERR_SUCCESS; | 
 |     } | 
 |     else if (code == 550) | 
 |     { | 
 |         LOGE("Dir has exist[%s].", path); | 
 |         return FTP_ERR_FILE_EXIST; | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGE("MKD rsp error[code = %d].", code); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 | } | 
 |  | 
 | static mbtk_ftp_error_enum ftp_cmd_process_rmd(mbtk_ftp_info_s *info, | 
 |         const char *path) | 
 | { | 
 |     int code; | 
 |     char cmd[100] = { 0 }; | 
 |     snprintf(cmd, 100, "RMD %s\r\n", path); | 
 |     code = ftp_cmd_handle(info, cmd, NULL, NULL); | 
 |     if (code == 250) | 
 |     { | 
 |         return FTP_ERR_SUCCESS; | 
 |     } | 
 |     else if (code == 550) | 
 |     { | 
 |         LOGE("Dir not exist or not empty[%s].", path); | 
 |         return FTP_ERR_FILE_NO_FOUND; | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGE("RMD rsp error[code = %d].", code); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 | } | 
 |  | 
 | static mbtk_ftp_error_enum ftp_cmd_process_stat(mbtk_ftp_info_s *info, | 
 |         void *status) | 
 | { | 
 |     int code; | 
 |     char rsp[1024]; | 
 |     uint32 rsp_len = 1024; | 
 |     code = ftp_cmd_handle(info, "STAT\r\n", rsp, &rsp_len); | 
 |     if (code != 211) | 
 |     { | 
 |         LOGE("STAT rsp error[code = %d].", code); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     memcpy(status, rsp, rsp_len); | 
 |  | 
 |     return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 | static mbtk_ftp_error_enum ftp_cmd_process_type(mbtk_ftp_info_s *info, | 
 |         mbtk_ftp_data_type_enum type) | 
 | { | 
 |     int code; | 
 |     if (type == FTP_DATA_TYPE_I) | 
 |         code = ftp_cmd_handle(info, "TYPE I\r\n", NULL, NULL); | 
 |     else if (type == FTP_DATA_TYPE_E) | 
 |         code = ftp_cmd_handle(info, "TYPE E\r\n", NULL, NULL); | 
 |     else | 
 |         code = ftp_cmd_handle(info, "TYPE A\r\n", NULL, NULL); | 
 |  | 
 |     if (code != 200) | 
 |     { | 
 |         LOGE("TYPE rsp error[code = %d].", code); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 | static mbtk_ftp_error_enum ftp_cmd_process_size(mbtk_ftp_info_s *info, | 
 |         const char *path, uint32 *size) | 
 | { | 
 |     int code; | 
 |     char cmd[100] = { 0 }; | 
 |     char rsp[100]; | 
 |     uint32 rsp_len = 100; | 
 |     snprintf(cmd, 100, "SIZE %s\r\n", path); | 
 |     code = ftp_cmd_handle(info, cmd, rsp, &rsp_len); | 
 |  | 
 |     if (code == 213) | 
 |     { | 
 |         // "213 4660645" | 
 |         *size = atoi(rsp + 4); | 
 |     } | 
 |     else if (code == 550) | 
 |     { | 
 |         LOGW("No found file[%s].", path); | 
 |         return FTP_ERR_FILE_NO_FOUND; | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGE("SIZE rsp error[code = %d].", code); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 | static mbtk_ftp_error_enum ftp_cmd_process_mdtm(mbtk_ftp_info_s *info, | 
 |         const char *path, char *time) | 
 | { | 
 |     int code; | 
 |     char cmd[100] = { 0 }; | 
 |     char rsp[100]; | 
 |     uint32 rsp_len = 100; | 
 |     snprintf(cmd, 100, "MDTM %s\r\n", path); | 
 |     code = ftp_cmd_handle(info, cmd, rsp, &rsp_len); | 
 |  | 
 |     if (code == 213) | 
 |     { | 
 |         // "213 20181017014716" | 
 |         memcpy(time, rsp + 4, 14); | 
 |     } | 
 |     else if (code == 550) | 
 |     { | 
 |         LOGW("No found file[%s].", path); | 
 |         return FTP_ERR_FILE_NO_FOUND; | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGE("MDTM rsp error[code = %d].", code); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 | static mbtk_ftp_error_enum ftp_cmd_process_dele(mbtk_ftp_info_s *info, | 
 |         const char *path) | 
 | { | 
 |     int code; | 
 |     char cmd[100] = { 0 }; | 
 |     snprintf(cmd, 100, "DELE %s\r\n", path); | 
 |     code = ftp_cmd_handle(info, cmd, NULL, NULL); | 
 |     if (code == 250) | 
 |     { | 
 |         return FTP_ERR_SUCCESS; | 
 |     } | 
 |     else if (code == 550) | 
 |     { | 
 |         LOGW("No found file[%s].", path); | 
 |         return FTP_ERR_FILE_NO_FOUND; | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGE("DELE rsp error[code = %d].", code); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 | } | 
 |  | 
 | static mbtk_ftp_error_enum ftp_cmd_process_quit(mbtk_ftp_info_s *info) | 
 | { | 
 |     int code; | 
 |     code = ftp_cmd_handle(info, "QUIT\r\n", NULL, NULL); | 
 |     if (code != 221) | 
 |     { | 
 |         LOGE("CWD rsp error[code = %d].", code); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 | static mbtk_ftp_error_enum ftp_cmd_process(mbtk_ftp_info_s *info, | 
 |         mbtk_ftp_cmd_enum cmd, void *req, void *rsp) | 
 | { | 
 |     mbtk_ftp_error_enum result = FTP_ERR_SUCCESS; | 
 |     if (info->state == FTP_STATE_READY)   // FTP login | 
 |     { | 
 |         info->state = FTP_STATE_CMD_PROCESS; | 
 |         switch (cmd) | 
 |         { | 
 |             case FTP_CMD_LIST: | 
 |             { | 
 |                 result = ftp_data_sock_read(info, FTP_CMD_LIST, req, rsp); | 
 |                 break; | 
 |             } | 
 |             case FTP_CMD_NLST: | 
 |             { | 
 |                 result = ftp_data_sock_read(info, FTP_CMD_NLST, req, rsp); | 
 |                 break; | 
 |             } | 
 |             case FTP_CMD_PWD: | 
 |             { | 
 |                 result = ftp_cmd_process_pwd(info, rsp); | 
 |                 break; | 
 |             } | 
 |             case FTP_CMD_CWD: | 
 |             { | 
 |                 result = ftp_cmd_process_cwd(info, (char*) req); | 
 |                 break; | 
 |             } | 
 |             case FTP_CMD_MKD: | 
 |             { | 
 |                 result = ftp_cmd_process_mkd(info, (char*) req); | 
 |                 break; | 
 |             } | 
 |             case FTP_CMD_RMD: | 
 |             { | 
 |                 result = ftp_cmd_process_rmd(info, (char*) req); | 
 |                 break; | 
 |             } | 
 |             case FTP_CMD_STAT: | 
 |             { | 
 |                 result = ftp_cmd_process_stat(info, rsp); | 
 |                 break; | 
 |             } | 
 |             case FTP_CMD_TYPE: | 
 |             { | 
 |                 mbtk_ftp_data_type_enum *type = (mbtk_ftp_data_type_enum*) req; | 
 |                 result = ftp_cmd_process_type(info, *type); | 
 |                 break; | 
 |             } | 
 |             case FTP_CMD_SIZE: | 
 |             { | 
 |                 result = ftp_cmd_process_size(info, (char*) req, (uint32*) rsp); | 
 |                 break; | 
 |             } | 
 |             case FTP_CMD_MDTM: | 
 |             { | 
 |                 result = ftp_cmd_process_mdtm(info, (char*) req, (char*) rsp); | 
 |                 break; | 
 |             } | 
 |             case FTP_CMD_DELE: | 
 |             { | 
 |                 result = ftp_cmd_process_dele(info, (char*) req); | 
 |                 break; | 
 |             } | 
 |             case FTP_CMD_QUIT: | 
 |             { | 
 |                 result = ftp_cmd_process_quit(info); | 
 |                 break; | 
 |             } | 
 |             default: | 
 |             { | 
 |                 LOGE("Unknown cmd:%d", cmd); | 
 |                 result = FTP_ERR_UNKNOWN; | 
 |                 break; | 
 |             } | 
 |         } | 
 |         info->state = FTP_STATE_READY; | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGW("FTP state error[%d].", info->state); | 
 |         result = FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     return result; | 
 | } | 
 |  | 
 | static mbtk_ftp_error_enum ftp_login(mbtk_ftp_info_s *info,mbtk_ftp_user_info_s *user) | 
 | { | 
 |     // Open net in the first. | 
 |     if(info->net_info.net_id <= 0) { | 
 |         if(sock_net_open(&info->net_info,info->sock_info[FTP_SOCK_CTRL].addr_family)) | 
 |         { | 
 |             LOGE("sock_net_open() fail."); | 
 |             return FTP_ERR_NET_CONN; | 
 |         } | 
 |     } | 
 |  | 
 |     int err; | 
 |     mbtk_ftp_error_enum ftp_err = FTP_ERR_SUCCESS; | 
 |     info->state = FTP_STATE_CONNECTING; | 
 |     info->net_info.keep_alive = TRUE; | 
 |     info->net_info.recv_buff_size = 0; // Default | 
 |     info->sock_info[FTP_SOCK_CTRL].fd = sock_open(&info->net_info, &info->sock_info[FTP_SOCK_CTRL], FTP_TIMEOUT, &err); | 
 |     if (info->sock_info[FTP_SOCK_CTRL].fd < 0)   // Fail | 
 |     { | 
 |         LOGE("Socket open/connect fail[err = %d].", err); | 
 |         ftp_err = FTP_ERR_NET_CONN; | 
 |         goto login_fail; | 
 |     } | 
 |  | 
 |     if(info->auth_type == FTP_AUTH_TYPE_IMPLICIT) | 
 |         info->sock_info[FTP_SOCK_CTRL].is_ssl = true; | 
 |  | 
 |     // Ctrl socket connect success. | 
 |     info->state = FTP_STATE_CONNECTED; | 
 |     LOGI("FTP ctrl socket connected."); | 
 |  | 
 |     char buff[1024]; | 
 |     int len; | 
 |     char *ptr = NULL; | 
 |  | 
 |     // 220-FileZilla Server version 0.9.43 beta | 
 |     // 220-written by Tim Kosse (tim.kosse@filezilla-project.org) | 
 |     // 220 Please visit http://sourceforge.net/projects/filezilla/ | 
 |     while(TRUE) { | 
 |         memset(buff, 0x0, 1024); | 
 |         len = sock_readline(&info->net_info, &info->sock_info[FTP_SOCK_CTRL], buff, 1024, FTP_TIMEOUT, | 
 |                             &err); | 
 |         if (len <= 0) | 
 |         { | 
 |             LOGE("Socket read fail[err = %d].", err); | 
 |             ftp_err = FTP_ERR_NET_READ; | 
 |             goto login_fail; | 
 |         } else {// xxx yyyyyy | 
 |             if((ptr = strstr(buff,"220 ")) || (ptr = strstr(buff,"230 "))) { | 
 |                 LOGI("RSP:%s",ptr); | 
 |                 break; | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |     int code = atoi(ptr); | 
 |     if (code == 230)   // Has logged in. | 
 |     { | 
 |         info->state = FTP_STATE_READY; | 
 |         LOGI("FTP Has logged in."); | 
 |         return FTP_ERR_SUCCESS; | 
 |     } | 
 |     else if (code == 220)       // Should logn in. | 
 |     { | 
 |         int len; | 
 |         char cmd_buff[50]; | 
 |  | 
 | #if 0 | 
 |         // Read other data. | 
 |         char buff[1024]; | 
 |         memset(buff,0x0,1024); | 
 |         while((len = sock_read(&info->net_info,info->ctrl_sock.fd, buff, 1024, info->ssl_enable, 1000, | 
 |                                 &err)) > 0) | 
 |         { | 
 |             LOGI("RSP[%d]:%s",len,buff); | 
 |             memset(buff,0x0,1024); | 
 |         } | 
 | #endif | 
 |  | 
 |         if(info->auth_type == FTP_AUTH_TYPE_EXPLICIT_SSL | 
 |             || info->auth_type == FTP_AUTH_TYPE_EXPLICIT_TLS) { | 
 |             if(info->auth_type == FTP_AUTH_TYPE_EXPLICIT_SSL) { | 
 |                 len = snprintf(cmd_buff, 50, "AUTH SSL\r\n"); | 
 |             } else { | 
 |                 len = snprintf(cmd_buff, 50, "AUTH TLS\r\n"); | 
 |             } | 
 |             cmd_buff[len] = '\0'; | 
 |             code = ftp_cmd_handle(info, cmd_buff, NULL, NULL); | 
 |             if (code != 234 && code != 334) | 
 |             { | 
 |                 LOGE("AUTH SSL/TLS fail[code = %d].", code); | 
 |                 ftp_err = FTP_ERR_LOGIN_DENIED; | 
 |                 goto login_fail; | 
 |             } | 
 |  | 
 | #if 0 | 
 |             if(sock_ssl_enable(&info->net_info,info->ctrl_sock.fd | 
 |                 ,info->ctrl_sock.host,info->ctrl_sock.port,info->use_cert,FTP_TIMEOUT)){ | 
 |                 LOGE("sock_ssl_enable() fail."); | 
 |                 ftp_err = FTP_ERR_LOGIN_DENIED; | 
 |                 goto login_fail; | 
 |             } | 
 | #endif | 
 |             info->sock_info[FTP_SOCK_CTRL].is_ssl = true; | 
 |         } | 
 |  | 
 |         if(info->auth_type != FTP_AUTH_TYPE_NON) { | 
 |             len = snprintf(cmd_buff, 50, "PBSZ 0\r\n"); | 
 |             cmd_buff[len] = '\0'; | 
 |             code = ftp_cmd_handle(info, cmd_buff, NULL, NULL); | 
 |             if (code != 200 && code != 220) | 
 |             { | 
 |                 LOGE("PBSZ 0 fail[code = %d].", code); | 
 |                 ftp_err = FTP_ERR_LOGIN_DENIED; | 
 |                 goto login_fail; | 
 |             } | 
 |         } | 
 |  | 
 |         len = snprintf(cmd_buff, 50, "USER %s\r\n", user->name); | 
 |         cmd_buff[len] = '\0'; | 
 |         code = ftp_cmd_handle(info, cmd_buff, NULL, NULL); | 
 |         if (code == 331) // USER is 331 | 
 |         { | 
 |             len = snprintf(cmd_buff, 50, "PASS %s\r\n", user->pass); | 
 |             cmd_buff[len] = '\0'; | 
 |             code = ftp_cmd_handle(info, cmd_buff, NULL, NULL); | 
 |         } | 
 |  | 
 |         if (code / 100 == 2)   // USER/PASS is 2xx | 
 |         { | 
 |             info->state = FTP_STATE_READY; | 
 |             LOGI("FTP logn in success."); | 
 |             return FTP_ERR_SUCCESS; | 
 |         } | 
 |         else if (code == 332)   // // USER/PASS is 332 | 
 |         { | 
 |             LOGW("Should set ACCT."); | 
 |             ftp_err = FTP_ERR_UNKNOWN; | 
 |             goto login_fail; | 
 |         } | 
 |         else | 
 |         { | 
 |             LOGE("FTP login denied[code = %d].", code); | 
 |             ftp_err = FTP_ERR_LOGIN_DENIED; | 
 |             goto login_fail; | 
 |         } | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGE("FTP code error[%d].", code); | 
 |         ftp_err = FTP_ERR_UNKNOWN; | 
 |         goto login_fail; | 
 |     } | 
 |  | 
 | login_fail: | 
 |     info->state = FTP_STATE_NON; | 
 |     return ftp_err; | 
 | } | 
 |  | 
 | static mbtk_ftp_info_s* ftp_info_find(mbtk_ftp_handle handle) | 
 | { | 
 |     if (!ftp_client_list) | 
 |     { | 
 |         LOGE("FTP Client List not init."); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     mbtk_ftp_info_s *result = NULL; | 
 |     list_first(ftp_client_list); | 
 |     while ((result = (mbtk_ftp_info_s*) list_next(ftp_client_list))) | 
 |     { | 
 |         if (result->handle == handle) | 
 |             break; | 
 |     } | 
 |  | 
 |     return result; | 
 | } | 
 |  | 
 | mbtk_ftp_handle mbtk_ftp_upload_end(mbtk_ftp_handle handle) | 
 | { | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         printf("No such FTP handle:%d\n", handle); | 
 |     } | 
 |  | 
 |     char buff[1024]={0}; | 
 |     int err=0; | 
 |     int len=0; | 
 |     int result; | 
 |  | 
 |     if (info->sock_info[FTP_SOCK_DATA].fd > 0) | 
 |     { | 
 |         if (sock_close(&info->net_info, &info->sock_info[FTP_SOCK_DATA], FTP_TIMEOUT, &err)) | 
 |         { | 
 |             LOGE("Close data socket fail[%d].", err); | 
 |             result = FTP_ERR_NET_CLOSE; | 
 |         } | 
 |         else | 
 |         { | 
 |         //    info->sock_info[FTP_SOCK_DATA].fd = -1; | 
 |         } | 
 |     } | 
 |     if(info->auth_type != 0) | 
 |     { | 
 |         if(mbtk_sock_close(info->ftp_ssl_handle,info->session_data,6000,&err)) | 
 |         { | 
 |             LOGE("Close ssl data socket fail[%d].", err); | 
 |             result = FTP_ERR_NET_CLOSE; | 
 |         } | 
 |         else | 
 |         { | 
 |         //    info->sock_info[FTP_SOCK_DATA].fd = -1; | 
 |         } | 
 |     } | 
 |     info->data_mode = FTP_MODE_PASSIVE; | 
 |     info->is_data_sock_busy = false; | 
 |     info->file_trans.size_count = 0; | 
 |     info->file_trans.size_send = 0; | 
 |  | 
 |     char line_buf[1024]; | 
 |     if(info->auth_type != 0) | 
 |         len = mbtk_sock_read(info->ftp_ssl_handle,info->session,buff,sizeof(buff),FTP_TIMEOUT,&err); | 
 |     else | 
 |         len = sock_readline(&info->net_info, &info->sock_info[FTP_SOCK_CTRL], buff, 1024, FTP_TIMEOUT, &err); | 
 |     if(len > 0) | 
 |     { | 
 |         printf("\n%s\n",buff); | 
 |         if(err != 0) | 
 |             printf("socket read error: %d\n",err); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("socket_read error:%d\n",err); | 
 |         result = -1; | 
 |     } | 
 |  | 
 |     return result; | 
 | } | 
 |  | 
 | static mbtk_ftp_handle ftp_next_handle() | 
 | { | 
 |     if (!ftp_client_list) | 
 |     { | 
 |         LOGE("FTP Client List not init."); | 
 |         return -1; | 
 |     } | 
 |  | 
 |     mbtk_ftp_info_s *info = NULL; | 
 |     mbtk_ftp_handle handle = 1; | 
 |     bool used; | 
 |     while (handle <= FTP_HANDLE_MAX) | 
 |     { | 
 |         used = false; | 
 |         // This handle used? | 
 |         list_first(ftp_client_list); | 
 |         while ((info = (mbtk_ftp_info_s*) list_next(ftp_client_list))) | 
 |         { | 
 |             if (handle == info->handle) | 
 |             { | 
 |                 used = true; | 
 |                 break; | 
 |             } | 
 |         } | 
 |  | 
 |         if (!used) | 
 |         { | 
 |             break; | 
 |         } | 
 |  | 
 |         handle++; | 
 |     } | 
 |  | 
 |     LOGI("Get free handle:%d", handle); | 
 |  | 
 |     return handle; | 
 | } | 
 |  | 
 | static void ftp_free_func(void *data) | 
 | { | 
 |     if (data) | 
 |     { | 
 |         mbtk_ftp_info_s *info = (mbtk_ftp_info_s*) data; | 
 |         LOGI("Free FTP client[handle = %d].", info->handle); | 
 |         free(info); | 
 |     } | 
 | } | 
 |  | 
 | /************************************************************* | 
 |  Public Function Definitions | 
 |  *************************************************************/ | 
 | mbtk_ftp_handle mbtk_ftp_init(const void* host, uint16 port, mbtk_ftp_auth_type_enum auth_type, | 
 |                               bool is_ipv6, bool use_cert) | 
 | { | 
 |     if (!ftp_client_list) | 
 |         ftp_client_list = list_create(ftp_free_func); | 
 |  | 
 |     if (!ftp_client_list) | 
 |     { | 
 |         LOGE("FTP Client List not init."); | 
 |         return -1; | 
 |     } | 
 |  | 
 |     if (list_size(ftp_client_list) > FTP_HANDLE_MAX) | 
 |     { | 
 |         LOGE("FTP client is full."); | 
 |         return -1; | 
 |     } | 
 |  | 
 |     if (host == NULL || strlen(host) == 0) | 
 |     { | 
 |         LOGE("Host error."); | 
 |         return -1; | 
 |     } | 
 |  | 
 |     if (port == 0) | 
 |     { | 
 |         port = FTP_SERVICE_PORT_DEF; | 
 |     } | 
 |  | 
 |     mbtk_ftp_info_s *info = (mbtk_ftp_info_s*) malloc(sizeof(mbtk_ftp_info_s)); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("malloc() fail."); | 
 |         return -1; | 
 |     } | 
 |     memset(info, 0x0, sizeof(mbtk_ftp_info_s)); | 
 |     list_add(ftp_client_list, info); | 
 |     memcpy(info->sock_info[FTP_SOCK_CTRL].host, host, strlen(host)); | 
 |     info->sock_info[FTP_SOCK_CTRL].port = port; | 
 |     // info->auth_type == FTP_AUTH_TYPE_IMPLICIT, info->is_ipv6 ? MBTK_ADDR_IPV6 : MBTK_ADDR_IPV4,info->use_cert, | 
 |     info->sock_info[FTP_SOCK_CTRL].is_ssl = (auth_type == FTP_AUTH_TYPE_IMPLICIT); | 
 |     info->sock_info[FTP_SOCK_CTRL].addr_family = is_ipv6 ? MBTK_ADDR_IPV6: MBTK_ADDR_IPV4; | 
 |     info->sock_info[FTP_SOCK_CTRL].use_cert = use_cert; | 
 |  | 
 |     info->handle = ftp_next_handle(); | 
 |     info->state = FTP_STATE_NON; | 
 |     info->data_mode = FTP_MODE_PASSIVE; | 
 |     info->sock_info[FTP_SOCK_CTRL].fd = -1; | 
 |     info->sock_info[FTP_SOCK_DATA].fd = -1; | 
 |     //info->is_ipv6 = is_ipv6; | 
 |     info->auth_type = auth_type; | 
 |     //info->use_cert = use_cert; | 
 |  | 
 |     LOGI("FTP info#host:%s,port:%d,ipv6:%d,ssl:%d,cert:%d",info->sock_info[FTP_SOCK_CTRL].host, | 
 |             info->sock_info[FTP_SOCK_CTRL].port, | 
 |             is_ipv6,info->auth_type,use_cert); | 
 |  | 
 |     if(auth_type != FTP_AUTH_TYPE_NON) | 
 |     { | 
 |         info->ftp_ssl_handle = mbtk_sock_init(&info->ftp_ssl_info); | 
 |         if(info->ftp_ssl_handle == -1) | 
 |         { | 
 |             printf("mbtk_sock_init error\n"); | 
 |         } | 
 |  | 
 |         info->ftp_sock_ssl_info = (mbtk_sock_info*) malloc(sizeof(mbtk_sock_info)); | 
 |         memset(info->ftp_sock_ssl_info, 0x0, sizeof(mbtk_sock_info)); | 
 |         info->ftp_sock_ssl_info->is_support_ssl = (auth_type != FTP_AUTH_TYPE_NON); | 
 |         info->ftp_sock_ssl_info->ftp_ssl_support = 1; | 
 |         info->ftp_sock_ssl_info->port = port; | 
 |         info->ftp_sock_ssl_info->type = MBTK_SOCK_TCP; | 
 |         info->ftp_sock_ssl_info->ingnore_cert = !use_cert; | 
 |         memcpy(info->ftp_sock_ssl_info->address, host, strlen(host)); | 
 |     } | 
 |     return info->handle; | 
 | } | 
 |  | 
 | mbtk_ftp_error_enum mbtk_ftp_reconfig(mbtk_ftp_handle handle,const void* host, uint16 port, mbtk_ftp_auth_type_enum auth_type, | 
 |                                       bool is_ipv6, bool use_cert) | 
 | { | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |     if(auth_type != FTP_AUTH_TYPE_NON) | 
 |     { | 
 |         info->ftp_sock_ssl_info = (mbtk_sock_info*) malloc(sizeof(mbtk_sock_info)); | 
 |         memset(info->ftp_sock_ssl_info, 0x0, sizeof(mbtk_sock_info)); | 
 |         if(host && strlen(host) > 0) | 
 |         { | 
 |             memcpy(info->ftp_sock_ssl_info->address, host, strlen(host)); | 
 |             info->ftp_sock_ssl_info->address[strlen(host)] = '\0'; | 
 |         } | 
 |         info->ftp_sock_ssl_info->is_support_ssl = (auth_type != FTP_AUTH_TYPE_NON); | 
 |         info->ftp_sock_ssl_info->ftp_ssl_support = 1; | 
 |         info->ftp_sock_ssl_info->port = port; | 
 |         info->ftp_sock_ssl_info->ingnore_cert = !use_cert; | 
 |         info->ftp_sock_ssl_info->type = MBTK_SOCK_TCP; | 
 |     } | 
 |     if(info->state == FTP_STATE_NON) | 
 |     { | 
 |         if(host && strlen(host) > 0) | 
 |         { | 
 |             memcpy(info->sock_info[FTP_SOCK_CTRL].host, host, strlen(host)); | 
 |             info->sock_info[FTP_SOCK_CTRL].host[strlen(host)] = '\0'; | 
 |         } | 
 |         info->sock_info[FTP_SOCK_CTRL].port = port; | 
 |         info->sock_info[FTP_SOCK_CTRL].addr_family = is_ipv6 ? MBTK_ADDR_IPV6 : MBTK_ADDR_IPV4; | 
 |         info->auth_type = auth_type; | 
 |         info->sock_info[FTP_SOCK_CTRL].use_cert = use_cert; | 
 |  | 
 |         return FTP_ERR_SUCCESS; | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGE("Not reset FTP config.The state is %d", info->state); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 | } | 
 |  | 
 | mbtk_ftp_error_enum mbtk_ftp_user_set(mbtk_ftp_handle handle,void* user,void* pass) | 
 | { | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     if(info->state == FTP_STATE_NON && !str_empty(user) && !str_empty(pass)) | 
 |     { | 
 |         memset(&info->user,0x0,sizeof(mbtk_ftp_user_info_s)); | 
 |         memcpy(info->user.name, user, strlen(user)); | 
 |         memcpy(info->user.pass, pass, strlen(pass)); | 
 |         return FTP_ERR_SUCCESS; | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGE("Not reset FTP config.The state is %d", info->state); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 | } | 
 |  | 
 | mbtk_ftp_error_enum mbtk_ftp_deinit(mbtk_ftp_handle handle) | 
 | { | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     if (list_remove(ftp_client_list, info)) | 
 |     { | 
 |         int err; | 
 |         if(info->auth_type == FTP_AUTH_TYPE_NON) { | 
 |             sock_close(&info->net_info, &info->sock_info[FTP_SOCK_CTRL], FTP_TIMEOUT, &err); | 
 |             sock_close(&info->net_info, &info->sock_info[FTP_SOCK_DATA], FTP_TIMEOUT, &err); | 
 |         } else { | 
 |             mbtk_sock_deinit(info->ftp_ssl_handle); | 
 |         } | 
 |         ftp_free_func(info); | 
 |     } | 
 |  | 
 |     return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 | /* | 
 |  * Quit FTP service. | 
 |  */ | 
 | mbtk_ftp_error_enum mbtk_ftp_quit(mbtk_ftp_handle handle) | 
 | { | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     int err = 0; | 
 |     if(info->sock_info[FTP_SOCK_CTRL].fd > 0) { | 
 |         mbtk_ftp_error_enum ftp_err = ftp_cmd_process(info, FTP_CMD_QUIT, NULL, | 
 |                                       NULL); | 
 |         if (ftp_err != FTP_ERR_SUCCESS) | 
 |         { | 
 |             LOGE("FTP QUIT fail[%d].", ftp_err); | 
 |             //return ftp_err; | 
 |         } | 
 |  | 
 |         // FTP quit success. | 
 |         info->state = FTP_STATE_CONNECTED; | 
 |     } | 
 |  | 
 |     if(info->auth_type == FTP_AUTH_TYPE_NON) { | 
 |         if (sock_close(&info->net_info, &info->sock_info[FTP_SOCK_CTRL], FTP_TIMEOUT, &err)) | 
 |         { | 
 |             LOGE("Close ctrl socket fail[%d].", err); | 
 |             return FTP_ERR_NET_CLOSE; | 
 |         } | 
 |  | 
 |         if (sock_close(&info->net_info, &info->sock_info[FTP_SOCK_DATA], FTP_TIMEOUT, &err)) | 
 |         { | 
 |             LOGE("Close data socket fail[%d].", err); | 
 |             return FTP_ERR_NET_CLOSE; | 
 |         } | 
 |     } else { | 
 |         if(mbtk_sock_close(info->ftp_ssl_handle,info->session,6000,&err)) | 
 |         { | 
 |             LOGE("Close ssl ctrl socket fail[%d].", err); | 
 |             //return FTP_ERR_NET_CLOSE; | 
 |         } | 
 |  | 
 |         if(mbtk_sock_close(info->ftp_ssl_handle,info->session_data,6000,&err)) | 
 |         { | 
 |             LOGE("Close ssl data socket fail[%d].", err); | 
 |             //return FTP_ERR_NET_CLOSE; | 
 |         } | 
 |     } | 
 |  | 
 |  | 
 |     info->state = FTP_STATE_NON; | 
 |     info->data_mode = FTP_MODE_PASSIVE; | 
 |     memset(&info->file_trans, 0x0, sizeof(mbtk_ftp_file_trans_info_s)); | 
 |     info->sock_info[FTP_SOCK_CTRL].fd = -1; | 
 |     info->sock_info[FTP_SOCK_DATA].fd = -1; | 
 |  | 
 |     return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 | mbtk_ftp_error_enum mbtk_ftp_net_close(mbtk_ftp_handle handle) | 
 | { | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     if(info->net_info.net_id > 0) { | 
 |         int err; | 
 |         if(sock_net_close(&info->net_info, FTP_TIMEOUT,&err)) | 
 |         { | 
 |             LOGE("sock_net_close() fail[%ld].",err); | 
 |             return FTP_ERR_NET_CLOSE; | 
 |         } | 
 |  | 
 |         info->net_info.net_id = -1; | 
 |     } | 
 |  | 
 |     return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 |  | 
 | mbtk_ftp_info_s* mbtk_ftp_info_get(mbtk_ftp_handle handle) | 
 | { | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     return info; | 
 | } | 
 |  | 
 | /* | 
 |  * Login specified FTP service. | 
 |  */ | 
 | mbtk_ftp_error_enum mbtk_ftp_login(mbtk_ftp_handle handle, void *name, | 
 |                                    void *pass) | 
 | { | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     if (info->state == FTP_STATE_NON) | 
 |     { | 
 |         mbtk_ftp_user_info_s user; | 
 |         memset(&user,0x0,sizeof(mbtk_ftp_user_info_s)); | 
 |         if (!str_empty(name) && !str_empty(pass)) | 
 |         { | 
 |             memcpy(user.name, name, strlen(name)); | 
 |             memcpy(user.pass, pass, strlen(pass)); | 
 |             memcpy(info->user.name, name, strlen(name)); | 
 |             memcpy(info->user.pass, pass, strlen(pass)); | 
 |         } | 
 |         else | 
 |         { | 
 |             memcpy(user.name, FTP_ANONYMOUS_USER, strlen(FTP_ANONYMOUS_USER)); | 
 |             memcpy(user.pass, FTP_ANONYMOUS_PASS, strlen(FTP_ANONYMOUS_PASS)); | 
 |             memcpy(info->user.name, FTP_ANONYMOUS_USER, strlen(FTP_ANONYMOUS_USER)); | 
 |             memcpy(info->user.pass, FTP_ANONYMOUS_PASS, strlen(FTP_ANONYMOUS_PASS)); | 
 |         } | 
 |  | 
 |         LOGI("FTP login#user:%s,pass:%s",user.name,user.pass); | 
 |  | 
 |         if(info->auth_type != 0) | 
 |         { | 
 |             int mbtk_errno=-1; | 
 |             info->session = mbtk_sock_open(info->ftp_ssl_handle,info->ftp_sock_ssl_info,60000,&mbtk_errno); | 
 |             if(mbtk_errno!=0) | 
 |             { | 
 |                 printf("mbtk_sock_open error : %d\n",mbtk_errno); | 
 |             } | 
 |             else | 
 |             { | 
 |                 unsigned char mbtk_ftp_ssl_read_buf[16384 + 1]; | 
 |                 char cmd[50]; | 
 |                 memset(cmd,0,50); | 
 |                 int len_ssl; | 
 |  | 
 |  | 
 |                 memset(cmd,0,50); | 
 |                 snprintf(cmd, 50, "PBSZ 0\r\n"); | 
 |                 mbtk_sock_write(info->ftp_ssl_handle,info->session, | 
 |                                     cmd, | 
 |                                     sizeof(cmd), | 
 |                                     60000, | 
 |                                     &mbtk_errno); | 
 |                 memset(mbtk_ftp_ssl_read_buf,0,sizeof(mbtk_ftp_ssl_read_buf)); | 
 |                 mbtk_sock_read(info->ftp_ssl_handle,info->session, | 
 |                             mbtk_ftp_ssl_read_buf, | 
 |                             sizeof(mbtk_ftp_ssl_read_buf), | 
 |                             60000, | 
 |                             &mbtk_errno); | 
 |                 printf("\nmbtk_sock_read PBSZ 0:\n%s\n",mbtk_ftp_ssl_read_buf); | 
 |                 memset(cmd,0,50); | 
 |                 snprintf(cmd, 50, "PROT P\r\n"); | 
 |                 mbtk_sock_write(info->ftp_ssl_handle,info->session, | 
 |                                     cmd, | 
 |                                     sizeof(cmd), | 
 |                                     60000, | 
 |                                     &mbtk_errno); | 
 |                 memset(mbtk_ftp_ssl_read_buf,0,sizeof(mbtk_ftp_ssl_read_buf)); | 
 |                 mbtk_sock_read(info->ftp_ssl_handle,info->session, | 
 |                             mbtk_ftp_ssl_read_buf, | 
 |                             sizeof(mbtk_ftp_ssl_read_buf), | 
 |                             60000, | 
 |                             &mbtk_errno); | 
 |                 printf("\nmbtk_sock_read PROT P:\n%s\n",mbtk_ftp_ssl_read_buf); | 
 |                 memset(cmd,0,50); | 
 |                 snprintf(cmd, 50, "USER %s\r\n",info->user.name); | 
 |                 mbtk_sock_write(info->ftp_ssl_handle,info->session, | 
 |                                     cmd, | 
 |                                     sizeof(cmd), | 
 |                                     60000, | 
 |                                     &mbtk_errno); | 
 |                 memset(mbtk_ftp_ssl_read_buf,0,sizeof(mbtk_ftp_ssl_read_buf)); | 
 |                 mbtk_sock_read(info->ftp_ssl_handle,info->session, | 
 |                             mbtk_ftp_ssl_read_buf, | 
 |                             sizeof(mbtk_ftp_ssl_read_buf), | 
 |                             60000, | 
 |                             &mbtk_errno); | 
 |                 printf("\nmbtk_sock_read USER:\n%s\n",mbtk_ftp_ssl_read_buf); | 
 |                 memset(cmd,0,50); | 
 |                 snprintf(cmd, 50, "PASS %s\r\n",info->user.pass); | 
 |                 mbtk_sock_write(info->ftp_ssl_handle,info->session, | 
 |                                     cmd, | 
 |                                     sizeof(cmd), | 
 |                                     60000, | 
 |                                     &mbtk_errno); | 
 |                 memset(mbtk_ftp_ssl_read_buf,0,sizeof(mbtk_ftp_ssl_read_buf)); | 
 |                 mbtk_sock_read(info->ftp_ssl_handle,info->session, | 
 |                             mbtk_ftp_ssl_read_buf, | 
 |                             sizeof(mbtk_ftp_ssl_read_buf), | 
 |                             60000, | 
 |                             &mbtk_errno); | 
 |                 printf("\nmbtk_sock_read PASS:\n%s\n",mbtk_ftp_ssl_read_buf); | 
 |                 char *ptr = NULL; | 
 |                 if((ptr = strstr(mbtk_ftp_ssl_read_buf,"220 ")) || (ptr = strstr(mbtk_ftp_ssl_read_buf,"230 "))) { | 
 |                     LOGI("RSP:%s",ptr); | 
 |                     printf("RSP:%s\n",ptr); | 
 |                 } | 
 |                 else | 
 |                 { | 
 |                     printf("\nptr error.\n"); | 
 |                     return FTP_ERR_UNKNOWN; | 
 |                 } | 
 |                 int code = atoi(ptr); | 
 |                 if (code / 100 == 2)   // USER/PASS is 2xx | 
 |                 { | 
 |                     info->state = FTP_STATE_READY; | 
 |                     LOGI("FTP logn in success."); | 
 |                     printf("FTP logn in success.\n"); | 
 |                 } | 
 |                 else if (code == 332)   // // USER/PASS is 332 | 
 |                 { | 
 |                     LOGW("Should set ACCT."); | 
 |                     printf("Should set ACCT.\n"); | 
 |                     return FTP_ERR_UNKNOWN; | 
 |                 } | 
 |                 else | 
 |                 { | 
 |                     LOGE("FTP login denied[code = %d].", code); | 
 |                     printf("FTP login denied[code = %d].\n", code); | 
 |                     return FTP_ERR_UNKNOWN; | 
 |                 } | 
 |  | 
 |                 memset(cmd,0,50); | 
 |                 snprintf(cmd, 50, "PWD\r\n"); | 
 |                 mbtk_sock_write(info->ftp_ssl_handle,info->session, | 
 |                                     cmd, | 
 |                                     sizeof(cmd), | 
 |                                     60000, | 
 |                                     &mbtk_errno); | 
 |                 memset(mbtk_ftp_ssl_read_buf,0,sizeof(mbtk_ftp_ssl_read_buf)); | 
 |                 mbtk_sock_read(info->ftp_ssl_handle,info->session, | 
 |                             mbtk_ftp_ssl_read_buf, | 
 |                             sizeof(mbtk_ftp_ssl_read_buf), | 
 |                             60000, | 
 |                             &mbtk_errno); | 
 |                 printf("\nmbtk_sock_read PWD:\n%s\n",mbtk_ftp_ssl_read_buf); | 
 |             } | 
 |             return mbtk_errno; | 
 |         } | 
 |  | 
 |         return ftp_login(info,&user); | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGD("Has login."); | 
 |         return FTP_ERR_SUCCESS; | 
 |     } | 
 | } | 
 |  | 
 | /* | 
 |  * Get current directory's path. | 
 |  */ | 
 | mbtk_ftp_error_enum mbtk_ftp_pwd(mbtk_ftp_handle handle, void *path) | 
 | { | 
 |     if (!path) | 
 |     { | 
 |         LOGE("No set path"); | 
 |         return FTP_ERR_PARAM_SET; | 
 |     } | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     return ftp_cmd_process(info, FTP_CMD_PWD, NULL, path); | 
 | } | 
 |  | 
 | /* | 
 |  * Go to specified directory. | 
 |  */ | 
 | mbtk_ftp_error_enum mbtk_ftp_cd(mbtk_ftp_handle handle, void *path) | 
 | { | 
 |     if (!path) | 
 |     { | 
 |         LOGE("No set path"); | 
 |         return FTP_ERR_PARAM_SET; | 
 |     } | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     return ftp_cmd_process(info, FTP_CMD_CWD, path, NULL); | 
 | } | 
 |  | 
 | /* | 
 |  * Get the native ip and free port. | 
 |  */ | 
 | mbtk_ftp_error_enum mbtk_ftp_get_ip_and_port(char *ipBuf_out, | 
 |                                     int *port,int iptype) | 
 | { | 
 |     char psz_port_cmd[128]; | 
 |     int i=0; | 
 |  | 
 |     *port = rand() % (60000 - 50000 + 1) + 50000; | 
 |     sprintf(psz_port_cmd, "netstat -an | grep :%d > /dev/null", *port); | 
 |  | 
 |         char ipBuf[32] = ""; | 
 |         FILE *fstream=NULL; | 
 |  | 
 |         char buff[1024]; | 
 |         char iptype_str[8]; | 
 |         memset(buff,0,sizeof(buff)); | 
 |         /*eth0可以换成eth1、docker0、em1、lo等*/ | 
 |         if(iptype == MBTK_ADDR_IPV6) | 
 |         { | 
 |  | 
 |             if(NULL==(fstream=popen("ifconfig ccinet0 | grep \"inet6 addr: 2\" | awk '{print $3}'","r"))) | 
 |             { | 
 |                 snprintf(ipBuf, 39, "%s","0:0:0:0:0:0:0:0"); | 
 |             } | 
 |             if(NULL!=fgets(buff, sizeof(buff), fstream)) | 
 |             { | 
 |                 snprintf(ipBuf, 39, "%s",buff); | 
 |             } | 
 |             else | 
 |             { | 
 |                 snprintf(ipBuf, 39, "%s","0:0:0:0:0:0:0:0"); | 
 |                 pclose(fstream); | 
 |             } | 
 |         } | 
 |         else | 
 |         { | 
 |             if(NULL==(fstream=popen("ifconfig ccinet0 | grep \"inet addr:\" | awk \'{print $2}\' | cut -c 6-","r"))) | 
 |             { | 
 |                 snprintf(ipBuf, 18, "%s","0.0.0.0"); | 
 |             } | 
 |             if(NULL!=fgets(buff, sizeof(buff), fstream)) | 
 |             { | 
 |                 snprintf(ipBuf, 18, "%s",buff); | 
 |             } | 
 |             else | 
 |             { | 
 |                 snprintf(ipBuf, 18, "%s","0.0.0.0"); | 
 |                 pclose(fstream); | 
 |             } | 
 |         } | 
 |             pclose(fstream); | 
 |  | 
 |         printf("ip:%s\n", ipBuf); | 
 |         memcpy(ipBuf_out, ipBuf, 32); | 
 |         return 0; | 
 | } | 
 | /* | 
 |  * Get current directory's subdirectory. | 
 |  */ | 
 | mbtk_ftp_error_enum mbtk_ftp_dir_ls(mbtk_ftp_handle handle, | 
 |                                     mbtk_ftp_file_info_s *list_head) | 
 | { | 
 |     if (!list_head) | 
 |     { | 
 |         LOGE("No set file list."); | 
 |         return FTP_ERR_PARAM_SET; | 
 |     } | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     return ftp_cmd_process(info, FTP_CMD_LIST, NULL, list_head); | 
 | } | 
 |  | 
 | /* | 
 |  * Get specified file's size. | 
 |  */ | 
 | uint32 mbtk_ftp_file_size(mbtk_ftp_handle handle, void *path) | 
 | { | 
 |     if (!path) | 
 |     { | 
 |         LOGE("No set path"); | 
 |         return 0; | 
 |     } | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return 0; | 
 |     } | 
 |     uint32 size = 0; | 
 |     if (ftp_cmd_process(info, FTP_CMD_SIZE, path, &size) != FTP_ERR_SUCCESS) | 
 |         return 0; | 
 |  | 
 |     return size; | 
 | } | 
 |  | 
 | /* | 
 |  * Get specified file's modify time. | 
 |  */ | 
 | mbtk_ftp_error_enum mbtk_ftp_file_time(mbtk_ftp_handle handle, void *path, | 
 |                                        void *time) | 
 | { | 
 |     if (!path) | 
 |     { | 
 |         LOGE("No set path"); | 
 |         return FTP_ERR_PARAM_SET; | 
 |     } | 
 |  | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     return ftp_cmd_process(info, FTP_CMD_MDTM, path, time); | 
 | } | 
 |  | 
 | /* | 
 |  * Delete specified file. | 
 |  */ | 
 | mbtk_ftp_error_enum mbtk_ftp_file_del(mbtk_ftp_handle handle, void *path) | 
 | { | 
 |     if (!path) | 
 |     { | 
 |         LOGE("No set path"); | 
 |         return FTP_ERR_PARAM_SET; | 
 |     } | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     return ftp_cmd_process(info, FTP_CMD_DELE, path, NULL); | 
 | } | 
 |  | 
 | /* | 
 |  * Create specified directory. | 
 |  */ | 
 | mbtk_ftp_error_enum mbtk_ftp_dir_mkdir(mbtk_ftp_handle handle, void *path) | 
 | { | 
 |     if (!path) | 
 |     { | 
 |         LOGE("No set path"); | 
 |         return FTP_ERR_PARAM_SET; | 
 |     } | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     return ftp_cmd_process(info, FTP_CMD_MKD, path, NULL); | 
 | } | 
 |  | 
 | /* | 
 |  * Delete specified directory. | 
 |  */ | 
 | mbtk_ftp_error_enum mbtk_ftp_dir_rmdir(mbtk_ftp_handle handle, void *path) | 
 | { | 
 |     if (!path) | 
 |     { | 
 |         LOGE("No set path"); | 
 |         return FTP_ERR_PARAM_SET; | 
 |     } | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     return ftp_cmd_process(info, FTP_CMD_RMD, path, NULL); | 
 | } | 
 |  | 
 | /* | 
 |  * Set data type. | 
 |  */ | 
 | mbtk_ftp_error_enum mbtk_ftp_data_type_set(mbtk_ftp_handle handle, | 
 |         mbtk_ftp_data_type_enum data_type) | 
 | { | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     return ftp_cmd_process(info, FTP_CMD_TYPE, &data_type, NULL); | 
 | } | 
 |  | 
 | /* | 
 |  * Set FTP mode. | 
 |  */ | 
 | mbtk_ftp_error_enum mbtk_ftp_mode_set(mbtk_ftp_handle handle, | 
 |                                       mbtk_ftp_mode_enum mode) | 
 | { | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     info->data_mode = mode; | 
 |  | 
 |     return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 | uint32 mbtk_ftp_download_start(mbtk_ftp_handle handle, void *remote_path, | 
 |                                void *local_path, mbtk_data_cb_func data_cb) | 
 | { | 
 |     if (!remote_path || (local_path && data_cb) || (!local_path && !data_cb)) | 
 |     { | 
 |         LOGE("Param set error."); | 
 |         return 0; | 
 |     } | 
 |  | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return 0; | 
 |     } | 
 |  | 
 |     if (info->state >= FTP_STATE_READY && !info->is_trans) | 
 |     { | 
 |         int retry_time = 0; | 
 |         memset(&info->file_trans, 0x0, sizeof(mbtk_ftp_file_trans_info_s)); | 
 |  | 
 |         // Set data type to "I" | 
 |         if (FTP_ERR_SUCCESS | 
 |             != mbtk_ftp_data_type_set(handle, FTP_DATA_TYPE_I)) | 
 |         { | 
 |             LOGE("Set data type to I fail."); | 
 |             return 0; | 
 |         } | 
 |  | 
 |         // Get file size. | 
 |         info->file_trans.size_count = mbtk_ftp_file_size(handle, remote_path); | 
 |         if (info->file_trans.size_count > 0) | 
 |         { | 
 |             LOGI("File size:%d", info->file_trans.size_count); | 
 |         } | 
 |         else | 
 |         { | 
 |             LOGE("File not exist."); | 
 |             return 0; | 
 |         } | 
 |  | 
 |         //Get file modify time. | 
 |         if (FTP_ERR_SUCCESS | 
 |             != mbtk_ftp_file_time(handle, remote_path, | 
 |                                   (char*) info->file_trans.modify_time)) | 
 |         { | 
 |             LOGE("Get file modify time fail."); | 
 |             return 0; | 
 |         } | 
 |  | 
 |         memcpy(info->file_trans.remote_name, remote_path, | 
 |                strlen((char*) remote_path)); | 
 |         if (local_path) | 
 |         { | 
 |             memcpy(info->file_trans.local_name, local_path, | 
 |                    strlen((char*) local_path)); | 
 |             info->file_trans.data_cb = NULL; | 
 |         } | 
 |         else | 
 |         { | 
 |             info->file_trans.data_cb = data_cb; | 
 |         } | 
 |         info->file_trans.size_send = 0; | 
 |         info->file_trans.is_download = true; | 
 |         info->file_trans.fd = -1; | 
 |         info->is_trans = true; | 
 |  | 
 |         if (!info->file_trans.data_cb)   // Save to efs | 
 |         { | 
 |             info->file_trans.fd = file_open((const char*)info->file_trans.local_name, | 
 |                                             O_WRONLY | O_CREAT | O_TRUNC); | 
 |             if (info->file_trans.fd <= 0) | 
 |             { | 
 |                 LOGE("Can not open EFS file[%s].", info->file_trans.local_name); | 
 |                 return 0; | 
 |             } | 
 |         } | 
 |  | 
 |         do { | 
 |             // Start download file. | 
 |             if (FTP_ERR_SUCCESS | 
 |                 != ftp_data_sock_read(info, FTP_CMD_GET, NULL, NULL)) | 
 |             { | 
 |                 LOGW("ftp_data_sock_read() fail."); | 
 |             } | 
 |  | 
 |             if(info->sock_info[FTP_SOCK_CTRL].fd <= 0) { | 
 |                 // Download fail. | 
 |                 LOGW("Ctrl socket error,should login angin."); | 
 |                 break; | 
 |             } else if (info->file_trans.size_send == info->file_trans.size_count) { | 
 |                 // Download success | 
 |                 break; | 
 |             } | 
 |  | 
 |             // Should redownload without quit. | 
 |             char time[20] = { 0 }; | 
 |             if (FTP_ERR_SUCCESS | 
 |                 != mbtk_ftp_file_time(handle, info->file_trans.remote_name, | 
 |                                       time)) | 
 |             { | 
 |                 LOGE("Get file modify time fail."); | 
 |                 break; | 
 |             } | 
 |  | 
 |             if (strcmp(time, (char*) info->file_trans.modify_time)) | 
 |             { | 
 |                 LOGW("Service file changed."); | 
 |                 break; | 
 |             } | 
 |  | 
 |             retry_time++; | 
 |         } while(retry_time < 5); | 
 |  | 
 |  | 
 |         if (!info->file_trans.data_cb && info->file_trans.fd > 0)   // Save to efs | 
 |         { | 
 |             if (file_close(info->file_trans.fd)) | 
 |             { | 
 |                 LOGE("EFS close fail."); | 
 |                 return 0; | 
 |             } | 
 |         } | 
 |  | 
 |         // Download success. | 
 |         if (info->file_trans.size_send == info->file_trans.size_count) | 
 |         { | 
 |             LOGI("Download %s success[%d].", (char* )remote_path, | 
 |                  info->file_trans.size_count); | 
 |  | 
 |             // Reset download configs. | 
 |             info->is_trans = false; | 
 |             // memset(&info->file_trans, 0x0, sizeof(mbtk_ftp_file_trans_info_s)); | 
 |         } | 
 |         else | 
 |         { | 
 |             LOGW("Download %s fail[%d / %d].", (char* )remote_path, | 
 |                  info->file_trans.size_send, info->file_trans.size_count); | 
 |         } | 
 |  | 
 |         return info->file_trans.size_send; | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGE("FTP state error[%d].", info->state); | 
 |         return 0; | 
 |     } | 
 | } | 
 |  | 
 | uint32 mbtk_ftp_download_continue(mbtk_ftp_handle handle) | 
 | { | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return 0; | 
 |     } | 
 |  | 
 |     if(info->state == FTP_STATE_NON) { | 
 |         if(FTP_ERR_SUCCESS != ftp_login(info,&info->user)) { | 
 |             LOGE("FTP login fail."); | 
 |             return 0; | 
 |         } | 
 |     } | 
 |  | 
 |     if (info->state >= FTP_STATE_READY && info->is_trans | 
 |         && info->file_trans.is_download | 
 |         && info->file_trans.size_send < info->file_trans.size_count) | 
 |     { | 
 |         // Set data type to "I" | 
 |         if (FTP_ERR_SUCCESS | 
 |             != mbtk_ftp_data_type_set(handle, FTP_DATA_TYPE_I)) | 
 |         { | 
 |             LOGE("Set data type to I fail."); | 
 |             return 0; | 
 |         } | 
 |  | 
 |         // Get file size. | 
 |         uint32 size = mbtk_ftp_file_size(handle, info->file_trans.remote_name); | 
 |         if (size > 0) | 
 |         { | 
 |             LOGI("File size:%d", size); | 
 |         } | 
 |         else | 
 |         { | 
 |             LOGE("File not exist."); | 
 |             return 0; | 
 |         } | 
 |         if (size != info->file_trans.size_count) | 
 |         { | 
 |             LOGW("Service file changed."); | 
 |             return 0; | 
 |         } | 
 |  | 
 |         //Get file modify time. | 
 |         char time[20] = { 0 }; | 
 |         if (FTP_ERR_SUCCESS | 
 |             != mbtk_ftp_file_time(handle, info->file_trans.remote_name, | 
 |                                   time)) | 
 |         { | 
 |             LOGE("Get file modify time fail."); | 
 |             return 0; | 
 |         } | 
 |         if (strcmp(time, (char*) info->file_trans.modify_time)) | 
 |         { | 
 |             LOGW("Service file changed."); | 
 |             return 0; | 
 |         } | 
 |  | 
 |         if (!info->file_trans.data_cb)   // Save to efs | 
 |         { | 
 |             info->file_trans.fd = file_open((const char*)info->file_trans.local_name, | 
 |                                             O_WRONLY | O_CREAT | O_APPEND); | 
 |             if (info->file_trans.fd <= 0) | 
 |             { | 
 |                 LOGE("Can not open EFS file[%s].", info->file_trans.local_name); | 
 |                 return FTP_ERR_EFS_FILE; | 
 |             } | 
 |         } | 
 |  | 
 |         uint32 size_last = info->file_trans.size_send; | 
 |         // Start download file. | 
 |         if (FTP_ERR_SUCCESS | 
 |             != ftp_data_sock_read(info, FTP_CMD_GET, NULL, NULL)) | 
 |         { | 
 |             LOGW("Data download fail."); | 
 |         } | 
 |  | 
 |         if (!info->file_trans.data_cb && info->file_trans.fd > 0) | 
 |         { | 
 |             if (file_close(info->file_trans.fd)) | 
 |             { | 
 |                 LOGE("EFS close fail."); | 
 |                 return 0; | 
 |             } | 
 |         } | 
 |  | 
 |         // Download success. | 
 |         if (info->file_trans.size_send == info->file_trans.size_count) | 
 |         { | 
 |             LOGI("Download %s success[%d].", info->file_trans.remote_name, | 
 |                  info->file_trans.size_count); | 
 |  | 
 |             // Reset download configs. | 
 |             info->is_trans = false; | 
 |             //memset(&info->file_trans, 0x0, sizeof(mbtk_ftp_file_trans_info_s)); | 
 |         } | 
 |         else | 
 |         { | 
 |             LOGW("Download %s fail[%d / %d].", info->file_trans.remote_name, | 
 |                  info->file_trans.size_send, info->file_trans.size_count); | 
 |         } | 
 |  | 
 |         return info->file_trans.size_send - size_last; | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGE("FTP state error[%d].", info->state); | 
 |         return 0; | 
 |     } | 
 | } | 
 |  | 
 | /* | 
 | * Upload EFS:  local_path is efs path;size_byte is 0. | 
 | * Upload data: local_path is NULL;size_byte is data size. | 
 | */ | 
 | int mbtk_ftp_upload_start(mbtk_ftp_handle handle, const void *remote_path, | 
 |                           const void *local_path, uint32 size_byte) | 
 | { | 
 |     if (!remote_path || (size_byte == 0 && !local_path) | 
 |         || (size_byte > 0 && local_path)) | 
 |     { | 
 |         LOGE("Param set error."); | 
 |         return -1; | 
 |     } | 
 |  | 
 | 	int result = 0; | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return -1; | 
 |     } | 
 |  | 
 |     LOGE("info->state:%d, info->is_trans:%d", info->state,info->is_trans); | 
 |  | 
 |     if (info->state >= FTP_STATE_READY && !info->is_trans) | 
 |     { | 
 | 		        // Set data type to "I" | 
 |         if (FTP_ERR_SUCCESS | 
 |             != mbtk_ftp_data_type_set(handle, FTP_DATA_TYPE_I)) | 
 |         { | 
 |             LOGE("Set data type to I fail."); | 
 |             return -1; | 
 |         } | 
 |  | 
 |         memset(&info->file_trans, 0x0, sizeof(mbtk_ftp_file_trans_info_s)); | 
 |         info->file_trans.is_download = false; | 
 |  | 
 |         memcpy(info->file_trans.remote_name, remote_path, | 
 |                strlen((char*) remote_path)); | 
 |  | 
 |         if (local_path) | 
 |         { | 
 |             memcpy(info->file_trans.local_name, local_path, | 
 |                    strlen((char*) local_path)); | 
 |             info->file_trans.fd = file_open((const char*)info->file_trans.local_name, | 
 |                                             O_RDONLY); | 
 |             if (info->file_trans.fd <= 0) | 
 |             { | 
 |                 LOGE("Can not open EFS file[%s].", info->file_trans.local_name); | 
 |                 return -1; | 
 |             } | 
 |  | 
 |         } | 
 |         info->file_trans.size_count = size_byte; | 
 |         info->file_trans.size_send = 0; | 
 |         // Start upload data. | 
 |  | 
 |  | 
 | 	    // Start update file. | 
 |         if (FTP_ERR_SUCCESS != ftp_data_sock_read(info, FTP_CMD_PUT, NULL, NULL)) | 
 |         { | 
 |             LOGW("ftp_data_sock_read() fail."); | 
 | 			if(info->file_trans.size_count == info->file_trans.size_send && info->file_trans.size_send != 0) | 
 | 			{ | 
 | 				result = FTP_ERR_SUCCESS; | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 			    mbtk_at_ftp_par.rest_size = info->file_trans.size_send; | 
 | 				result = FTP_ERR_UNKNOWN; | 
 | 			} | 
 |         } | 
 |  | 
 | 		if (info->file_trans.fd > 0 )   // Save to efs | 
 | 		{ | 
 |             info->file_trans.size_count = 0; | 
 | 			info->file_trans.size_send = 0; | 
 | 			if (file_close(info->file_trans.fd)) | 
 | 			{ | 
 | 				LOGE("EFS close fail."); | 
 | 				return -1; | 
 | 			} | 
 | 		} | 
 |  | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGE("FTP state error[%d].", info->state); | 
 |         return -1; | 
 |     } | 
 |  | 
 |     return result; | 
 | } | 
 |  | 
 | /* | 
 | * This only for upload data(No for upload efs). | 
 | */ | 
 | int mbtk_ftp_upload_send(mbtk_ftp_handle handle, const void *data,uint16 data_len) | 
 | { | 
 |     if (!data || data_len == 0) | 
 |     { | 
 |         LOGE("Param set error."); | 
 |         return -1; | 
 |     } | 
 |  | 
 |     int err; | 
 | 	int result = 0; | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return -1; | 
 |     } | 
 |  | 
 |     if(info->file_trans.fd > 0)   // Is upload from efs. | 
 |     { | 
 |         LOGE("Not upload from EFS."); | 
 |         return -1; | 
 |     } | 
 |  | 
 | //LOGE("1socket:%d, data:%s, data_len:%d", info->sock_info[FTP_SOCK_DATA].fd, data, data_len ); | 
 |     if((info->file_trans.size_send + data_len) > info->file_trans.size_count) | 
 | 	{ | 
 | 		printf("send over set length\n"); | 
 |         result = FTP_ERR_UNKNOWN; | 
 |         goto overlong; | 
 |     } | 
 |     int len; | 
 |     if(info->auth_type != 0) | 
 |         len = mbtk_sock_write(info->ftp_ssl_handle,info->session_data,data,data_len,FTP_TIMEOUT,&err); | 
 |     else | 
 | 	    len = sock_write(&info->net_info, &info->sock_info[FTP_SOCK_DATA], data, data_len, | 
 |                             FTP_TIMEOUT, &err); | 
 | 	if(len < 0) | 
 | 	{ | 
 | 		LOGE("EFS write fail.len:%d, err;%d", len, err); | 
 |         return FTP_ERR_EFS_FILE; | 
 | 	} | 
 |  | 
 | 	info->file_trans.size_send += len; | 
 |     mbtk_at_ftp_par.rest_size = info->file_trans.size_send; | 
 |  | 
 |     LOGE("size_count:%d, size_send:%d.", info->file_trans.size_count,info->file_trans.size_send); | 
 |  | 
 |     if((info->file_trans.size_count <= info->file_trans.size_send) ) | 
 | 	{ | 
 | 	    printf("\nClose data socket begin!\n "); | 
 | 			    // Close data socket. | 
 | overlong:    if (info->sock_info[FTP_SOCK_DATA].fd > 0) | 
 | 	    { | 
 | 	        if (sock_close(&info->net_info, &info->sock_info[FTP_SOCK_DATA], FTP_TIMEOUT, &err)) | 
 | 	        { | 
 | 	            LOGE("Close data socket fail[%d].", err); | 
 |                 printf("\nClose data socket fail[%d].\n", err); | 
 | 	            result = FTP_ERR_NET_CLOSE; | 
 | 	        } | 
 | 	        else | 
 | 	        { | 
 | 	            printf("\nClose data socket ok[%d].\n", err); | 
 | 	        //    info->sock_info[FTP_SOCK_DATA].fd = -1; | 
 | 	        } | 
 | 	    } | 
 |         if(info->auth_type != 0) | 
 |         { | 
 |             if(mbtk_sock_close(info->ftp_ssl_handle,info->session_data,6000,&err)) | 
 |             { | 
 | 	            LOGE("Close ssl data socket fail[%d].", err); | 
 |                 printf("\nClose ssl data socket fail[%d].\n", err); | 
 | 	            result = FTP_ERR_NET_CLOSE; | 
 | 	        } | 
 | 	        else | 
 | 	        { | 
 | 	            printf("\nClose ssl data socket ok[%d].\n", err); | 
 | 	        //    info->sock_info[FTP_SOCK_DATA].fd = -1; | 
 | 	        } | 
 |         } | 
 |         info->data_mode = FTP_MODE_PASSIVE; | 
 |         info->is_data_sock_busy = false; | 
 |         info->file_trans.size_count = 0; | 
 |         info->file_trans.size_send = 0; | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		LOGE("size_count:%d, size_send:%d.", info->file_trans.size_count,info->file_trans.size_send); | 
 | 	} | 
 |  | 
 |  | 
 |     // Start update data. | 
 |  | 
 |     return result; | 
 | } | 
 |  | 
 | mbtk_ftp_error_enum mbtk_ftp_trans_reset(mbtk_ftp_handle handle) | 
 | { | 
 |     mbtk_ftp_info_s *info = ftp_info_find(handle); | 
 |     if (!info) | 
 |     { | 
 |         LOGE("No such FTP handle:%d", handle); | 
 |         return FTP_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     info->is_trans = false; | 
 |     memset(&info->file_trans, 0x0, sizeof(mbtk_ftp_file_trans_info_s)); | 
 |  | 
 |     return FTP_ERR_SUCCESS; | 
 | } | 
 |  | 
 | void mbtk_ftp_lib_info_print() | 
 | { | 
 |     MBTK_SOURCE_INFO_PRINT("mbtk_ftp_lib"); | 
 | } | 
 |  |