Files
2023-Webservices_And_Applic…/project/Core/Src/tftp.c
Sani7 e1118908d9 TFTP
Move over to the new fread that Lorentz is implementing
2023-11-11 00:38:39 +01:00

154 lines
4.3 KiB
C

/**
* @file tftp.c
* @brief tftp server
* @author Speetjens S.
*/
#include "tftp.h"
static const char* TAG = "tftp_server";
extern struct llfs_data_file* llfs_root;
static llfs_file_t virt_file[2] = {
{.name = "index.txt", .data = "test", .len = 4},
{.name = "virtImage.raw", .data = "test", .len = 4}
};
int str_cat_str(char* dest, int dest_size, const char* src) {
int dest_len = strlen(dest);
int src_len = strlen(src);
if (dest_len + src_len > dest_size) {
return -1;
}
memcpy(dest + dest_len, src, src_len);
return 0;
}
int str_cat(char* dest, int dest_size, char c)
{
int dest_len = strlen(dest);
if (dest_len + 1 > dest_size) {
return -1;
}
dest[dest_len] = c;
dest[dest_len + 1] = '\0';
return 0;
}
/**
* @brief tftp helper functions
*/
/**
* @brief This function is called when a file is opened
* It should return a handle to the file or NULL if the file does not exist
* The handle contains a ptr to or the actual file data or a virtual file
*
* @param fname The name of the file to open
* @param mode Mode string from TFTP RFC
* @param write Flag indicating read (0) or write (!= 0) access
* @return void* File handle supplied to other functions
*/
void* tftp_open(const char* fname, const char* mode, u8_t write) {
LOG_INFO(TAG, "Opening %s", fname);
if (strcmp(fname, virt_file[0].name) == 0 && write == TFTP_READ) {
return &virt_file[0];
} else if (strcmp(fname, virt_file[1].name) == 0 && write != TFTP_READ) {
return &virt_file[1];
}
// TODO: waiting on Lorentz to finish creating f* functions for LLFS
return fopen(fname, write ? "wb" : "rb");
}
/**
* @brief This function is called when a file is closed
*
* @param handle The handle to the file to close
*/
void tftp_close(void* handle) {
LOG_INFO(TAG, "closing file");
if (handle == NULL) {
LOG_CRIT(TAG, "handle is null");
return;
}
if (handle == &virt_file[0] || handle == &virt_file[1]) {
return;
}
// TODO: waiting on Lorentz to finish creating f* functions for LLFS
fclose((FILE*)handle);
}
/**
* @brief This function is called when a file is read
* The virtual files are filtered out first
* then the file is trying to get read from the llfs
*
* @param handle File handle returned by open()
* @param buf Target buffer to copy read data to
* @param bytes Number of bytes to copy to buf
* @return int >= 0: Success; < 0: Error
*/
int tftp_read(void* handle, void* buf, int bytes) {
LOG_INFO(TAG, "reading file");
if (handle == NULL) {
LOG_CRIT(TAG, "handle is null");
return -1;
}
FILE* file = (FILE*)handle;
LOG_INFO(TAG, "reading file: %s", file->name);
if (file == &virt_file[0]) {
const struct llfs_data_file* root = llfs_root;
str_cat_str(buf, bytes, virt_file[0].name);
str_cat(buf, bytes, '\n');
str_cat_str(buf, bytes, virt_file[1].name);
str_cat(buf, bytes, '\n');
while(root != NULL) {
str_cat(buf, bytes, root->name);
str_cat(buf, bytes, '\n');
file = root->next;
}
} else if (file == &virt_file[1]) {
LOG_CRIT(TAG, "Exception: Trying to read a write only file");
return -1;
}
// TODO: waiting on Lorentz to finish creating f* functions for LLFS
fread(buf, sizeof(uint8_t), bytes, file);
return 0;
}
/**
* @brief This function is called when a file is written
*
* @param handle File handle returned by open()
* @param p PBUF adjusted such that payload pointer points to the beginning of write data.
* In other words, TFTP headers are stripped off.
* @return int >= 0: Success; < 0: Error
*/
int tftp_write(void* handle, struct pbuf* p) {
LOG_INFO(TAG, "Writing file");
LOG_DEBUG(TAG, "Not implemented yet");
}
struct tftp_context tftpContext_s = {
.open = tftp_open,
.close = tftp_close,
.read = tftp_read,
.write = tftp_write
};
/**
* @brief Initialize tftp server
*/
void tftp_server_init(void) {
LOG_INFO(TAG, "Initializing tftp server");
if (tftp_init(&tftpContext_s) != ERR_OK) {
LOG_FATAL(TAG, "Could not initialize tftp server");
return;
}
LOG_INFO(TAG, "tftp server initialized successfully");
}