LwFTP/LWFTPC/lwftpc.c

276 lines
7.0 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);
}
//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;
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);
onDataReceived(data, len);
} while (netbuf_next(d_buf) >= 0);
netbuf_delete(d_buf);
} 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");
}