/* * lwftpc.c * * Created on: Feb 20, 2024 * Author: "SeungJu Lim" */ #include "lwftpc.h" /** send the data to the connected connection */ err_t lwftp_send(struct netconn *conn, const char *data) { err_t err = 0; if (strcmp(data, "\r\n") == 0) printf(">> lwftp: ----> send \r\n"); else printf(">> lwftp: ----> send %s", data); err = netconn_write(conn, data, strlen(data), NETCONN_COPY); #if FTPSemaphore // relaese the semaphore sys_sem_signal(&ftpsem); #endif return err; } err_t lwftp_data_open(lwftp_session_t *s, const char *response) { err_t err = ERR_VAL; char *ptr; ip_addr_t addr_d; ptr = strchr(response, '('); if (ptr) { unsigned int a = strtoul(ptr + 1, &ptr, 10); unsigned int b = strtoul(ptr + 1, &ptr, 10); unsigned int c = strtoul(ptr + 1, &ptr, 10); unsigned int d = strtoul(ptr + 1, &ptr, 10); IP4_ADDR(&addr_d, a, b, c, d); s->data_port = strtoul(ptr + 1, &ptr, 10) << 8; s->data_port |= strtoul(ptr + 1, &ptr, 10) & 255; printf(">> lwftp: server data port: '%d'\r\n", s->data_port); if (*ptr == ')') { s->data_conn = netconn_new(NETCONN_TCP); if (s->data_conn != NULL) { err = netconn_connect(s->data_conn, &addr_d, s->data_port); } else { err = ERR_MEM; } } } else { err = ERR_BUF; } return err; } /** *============================================= * Main functions *============================================= */ /* Send data to Server*/ err_t lwftp_store(lwftp_session_t *s, const char *filename, const char *data) { char cmd[256]; err_t err; size_t data_len = strlen(data); snprintf(cmd, sizeof(cmd), "STOR %s\r\n", filename); err = lwftp_send(s->conn, cmd); if (err == ERR_OK) { err = netconn_write(s->data_conn, data, data_len, NETCONN_COPY); if (err == ERR_OK) { printf(">> lwftp: data sent successfully\r\n"); netconn_close(s->data_conn); }else{ printf(">> lwftp: send data failed with code %d\r\n", err); } }else{ printf(">> lwftp: send command failed with code %d\r\n", err); } return err; } /* Get data from Server*/ err_t lwftp_retrieve(lwftp_session_t *s, const char *filename) { char cmd[256]; err_t err; snprintf(cmd, sizeof(cmd), "RETR %s\r\n", filename); err = lwftp_send(s->conn, cmd); if (err == ERR_OK) { printf(">> lwftp: command sent successfully\r\n"); } else { printf(">> lwftp: send command failed with code %d\r\n", err); } return err; } /* Get file list from Server*/ err_t lwftp_list(lwftp_session_t *s) { err_t err; err = lwftp_send(s->conn, "LIST\r\n"); if (err == ERR_OK) { printf(">> lwftp: command sent successfully\r\n"); } else { printf(">> lwftp: send command failed with code %d\r\n", err); } return err; } void onDataReceived(void *data, size_t size) { osDelay(1000); // printf("%s\r\n", (char*) data); printf("Received data (%zu bytes): %.*s\n", size, (int)size, (char*)data); } //void lwftp_data_thread(void *arg) { // lwftp_session_t *s = (lwftp_session_t*) arg; // static struct netbuf *d_buf; // // while (1) { // if (s->data_conn != NULL && s->data_state == LWFTP_CONNECTED) { // if (netconn_recv(s->data_conn, &d_buf) == ERR_OK) { // void *data; // u16_t len; // do { // netbuf_data(d_buf, &data, &len); // } while (netbuf_next(d_buf) >= 0); // onDataReceived(data, len); // } // if (d_buf != NULL) { // netbuf_delete(d_buf); // d_buf = NULL; // } // } // } //} void lwftp_data_thread(void *arg) { lwftp_session_t *s = (lwftp_session_t*) arg; static struct netbuf *d_buf; static char *aggregated_data = NULL; static size_t total_len = 0; while (1) { if (s->data_conn != NULL && s->data_state == LWFTP_CONNECTED) { err_t err = netconn_recv(s->data_conn, &d_buf); if (err == ERR_OK && d_buf != NULL) { void *data; u16_t len; do { netbuf_data(d_buf, &data, &len); if (aggregated_data == NULL) { aggregated_data = (char*) malloc(len); if (!aggregated_data) { break; } memcpy(aggregated_data, data, len); total_len = len; } else { char *new_data = (char*) realloc(aggregated_data, total_len + len); if (!new_data) { free(aggregated_data); aggregated_data = NULL; break; } aggregated_data = new_data; memcpy(aggregated_data + total_len, data, len); total_len += len; } } while (netbuf_next(d_buf) >= 0); netbuf_delete(d_buf); if (aggregated_data != NULL) { // onDataReceived(aggregated_data, total_len); free(aggregated_data); aggregated_data = NULL; total_len = 0; } } else { } } else { vTaskDelay(pdMS_TO_TICKS(100)); } } } void lwftp_ctrl_thread(void *arg) { lwftp_session_t *s = (lwftp_session_t*) arg; static struct netbuf *buf; uint response = 0; char cmd[256]; err_t err; // check session data invalid if ((s->control_state != LWFTP_CLOSED) || s->conn || s->data_conn || !s->user || !s->pass) { printf(">> lwftp: invalid session data\r\n"); return; } s->conn = netconn_new(NETCONN_TCP); s->data_conn = netconn_new(NETCONN_TCP); // create a new connection identifier if (s->conn != NULL) { err = netconn_bind(s->conn, &s->cli_ip, 0); if (err == ERR_OK) { printf(">> lwftp: client IP bind OK\r\n"); err = netconn_connect(s->conn, &s->svr_ip, s->svr_port); // If the connection to the server is established, the following will continue, else delete the connection if (err == ERR_OK) { printf(">> lwftp: server connect OK\r\n"); #if FTPSemaphore // Release the semaphore once the connection is successful sys_sem_signal(&ftpsem); #endif /** * ===================== * Response processing * ===================== */ while (1) { /* wait until the data is sent by the server*/ if (netconn_recv(s->conn, &buf) == ERR_OK) { if (buf) { response = strtoul(buf->p->payload, NULL, 10); printf("\n>> lwftp: <==== resp '%d'\r\n", response); /** [Response 220] Service ready for new user.*/ if (response == 220) { snprintf(cmd, sizeof(cmd), "USER %s\r\n", s->user); lwftp_send(s->conn, cmd); } /** [Response 331] User name okay, need password.*/ else if (response == 331) { snprintf(cmd, sizeof(cmd), "PASS %s\r\n", s->pass); lwftp_send(s->conn, cmd); } /** [Response 230] User logged in, proceed.*/ else if (response == 230) { printf(">> lwftp: now logged in\r\n"); lwftp_send(s->conn, "PASV\r\n"); } /** [Response 227] Entering Passive Mode (h1,h2,h3,h4,p1,p2).*/ else if (response == 227) { printf(">> lwftp: entering passive Mode\r\n"); err = lwftp_data_open(s, buf->p->payload); if (err != ERR_OK) { printf(">> lwftp: data port connection failed with code %d\r\n",err); goto exit; } s->data_state = LWFTP_CONNECTED; printf(">> lwftp: data port connect OK\r\n"); } /** [Response 125] Data connection already open; transfer starting.*/ else if (response == 125) { printf(">> lwftp: transfer starting.\r\n"); } /** [Response 226] Closing data connection. Requested file action successful*/ else if (response == 226) { printf(">> lwftp: closing data connection.\r\n"); printf(">> lwftp: requested file action successful.\r\n"); } } } memset(cmd, 0, sizeof(cmd)); if (buf != NULL) { netbuf_delete(buf); buf = NULL; } } } else { printf(">> lwftp: server connection failed with code %d\r\n", err); goto exit; } } else { printf(">> lwftp: client IP binding failed with code %d\r\n", err); goto exit; } } exit: if (s->data_conn) { netconn_close(s->data_conn); netconn_delete(s->data_conn); } netconn_close(s->conn); netconn_delete(s->conn); printf(">> lwftp: all ftp connection closed\r\n"); }