/** * @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} }; /** * @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); llfs_file_t* file; 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]; } return llfs_file_open(fname); } /** * @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"); } /** * @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_ERROR(TAG, "handle is null"); return -1; } llfs_file_t* file = (llfs_file_t*)handle; LOG_INFO(TAG, "reading file: %s", file->name); if (file == &virt_file[0]) { const struct llfs_data_file* root = llfs_root; while(root != NULL) { snprintf(buf, bytes, "%s\n", root->name); file = root->next; } } else if (file == &virt_file[1]) { LOG_CRIT(TAG, "Exception: Trying to read a write only file"); return -1; } memcpy(buf, file->data, bytes); return 0; } 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"); }