303 lines
7.8 KiB
C
303 lines
7.8 KiB
C
/*
|
|
* 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 <CRLF>\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");
|
|
}
|