From cc659b8b11a1eaa559b726d13b0f3987de97df12 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Fri, 10 Nov 2023 23:38:09 -0600 Subject: [PATCH] Progress: Further work in TacocaT. --- data/build/tacocat/dependencies | 1 + data/build/tacocat/settings | 2 +- sources/c/tacocat/main/common/define.h | 8 ++-- sources/c/tacocat/main/print/error.c | 56 +++++++++++++++++++++++-- sources/c/tacocat/main/print/error.h | 72 +++++++++++++++++++++++++++++++-- sources/c/tacocat/main/receive.c | 4 +- sources/c/tacocat/main/send.c | 74 ++++++++++++++++++++++++++++------ sources/c/tacocat/main/send.h | 3 ++ sources/c/tacocat/main/tacocat.h | 1 + 9 files changed, 195 insertions(+), 26 deletions(-) diff --git a/data/build/tacocat/dependencies b/data/build/tacocat/dependencies index 50c514d..f3be563 100644 --- a/data/build/tacocat/dependencies +++ b/data/build/tacocat/dependencies @@ -18,6 +18,7 @@ f_pipe f_print f_signal f_socket +f_status_string f_thread f_time diff --git a/data/build/tacocat/settings b/data/build/tacocat/settings index 4bc96ad..42f3596 100644 --- a/data/build/tacocat/settings +++ b/data/build/tacocat/settings @@ -32,7 +32,7 @@ build_indexer_arguments rcs build_language c build_libraries -lc -build_libraries-individual -lfll_error -lfll_print -lfll_program -lfl_conversion -lfl_fss -lfl_print -lf_color -lf_compare -lf_console -lf_conversion -lf_file -lf_fss -lf_memory -lf_network -lf_path -lf_pipe -lf_print -lf_signal -lf_socket -lf_string -lf_time -lf_type_array -lf_utf +build_libraries-individual -lfll_error -lfll_print -lfll_program -lfl_conversion -lfl_fss -lfl_print -lf_color -lf_compare -lf_console -lf_conversion -lf_file -lf_fss -lf_memory -lf_network -lf_path -lf_pipe -lf_print -lf_signal -lf_socket -lf_status_string -lf_string -lf_time -lf_type_array -lf_utf build_libraries-individual_thread -lf_thread build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll diff --git a/sources/c/tacocat/main/common/define.h b/sources/c/tacocat/main/common/define.h index 390047d..7037f7a 100644 --- a/sources/c/tacocat/main/common/define.h +++ b/sources/c/tacocat/main/common/define.h @@ -41,6 +41,7 @@ extern "C" { * - maintain: The max size in bytes to maintain a particular buffer. * * kt_tacocat_packet_*_d: + * - headers: The number of header Objects in the abstruse to create for sending a packet (type, name, part, size, status, and total). * - minimum: The minimum packet size, "header:\npayload:\n" = 17. * - peek: The size to peek into the packet to get the initial information. * - prebuffer: A size used to include during allocation to add additional space for the packet header and therefore help reduce the potential number of allocations. @@ -72,10 +73,11 @@ extern "C" { #define kt_tacocat_max_buffer_d 0x10000000 // 0x10^0x5 * 0x100 (Which is 256 Megabytes (0x10^0x5 where the base unit is 16 rather than 10 or 2 (maybe call this xytes? Megaxytes?)). #define kt_tacocat_max_maintain_d 0x100000 // 0x10^5 (Which is 1 Megabyte in base 16 (1 Megaxyte (MX)). - #define kt_tacocat_packet_minimum_d 17 - #define kt_tacocat_packet_peek_d 64 + #define kt_tacocat_packet_headers_d 0x6 + #define kt_tacocat_packet_minimum_d 0x11 + #define kt_tacocat_packet_peek_d 0x40 #define kt_tacocat_packet_prebuffer_d 0x200 - #define kt_tacocat_packet_read_d 0x2000 + #define kt_tacocat_packet_read_d 0x8000 #define kt_tacocat_signal_check_d 0x4e20 #define kt_tacocat_signal_check_failsafe_d 0x4e20 diff --git a/sources/c/tacocat/main/print/error.c b/sources/c/tacocat/main/print/error.c index 82901cc..d8f068b 100644 --- a/sources/c/tacocat/main/print/error.c +++ b/sources/c/tacocat/main/print/error.c @@ -86,6 +86,32 @@ extern "C" { } #endif // _di_kt_tacocat_print_error_on_buffer_too_large_ +#ifndef _di_kt_tacocat_print_error_on_file_too_large_ + f_status_t kt_tacocat_print_error_on_file_too_large(fl_print_t * const print, f_string_static_t file, f_string_static_t on, const f_string_static_t network, const f_number_unsigned_t size_expect, const f_number_unsigned_t size_got) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QFile '%] ", print->to, print->set->error, print->prefix, print->set->error); + fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, on, print->set->notable); + fl_print_format(" %[' for '%]", print->to, print->set->error, print->set->error, f_string_eol_s); + fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, on, print->set->notable); + fl_print_format(" %[ for '%]", print->to, print->set->error, print->set->error, f_string_eol_s); + fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, network, print->set->notable); + fl_print_format("%[', the maximum size is%] ", print->to, print->set->error, print->set->error); + fl_print_format("%[%ul%]", print->to, print->set->notable, size_expect, print->set->notable); + fl_print_format("%[, and the provided size is%] ", print->to, print->set->error, print->set->error); + fl_print_format("%[%ul%]", print->to, print->set->notable, size_got, print->set->notable); + fl_print_format(f_string_format_sentence_end_s.string, print->to, print->set->error, print->set->error, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_okay; + } +#endif // _di_kt_tacocat_print_error_on_file_too_large_ + #ifndef _di_kt_tacocat_print_error_on_busy_ f_status_t kt_tacocat_print_error_on_busy(fl_print_t * const print, f_string_static_t on, const f_string_static_t network) { @@ -106,8 +132,30 @@ extern "C" { } #endif // _di_kt_tacocat_print_error_on_busy_ -#ifndef _di_kt_tacocat_print_error_on_file_ - f_status_t kt_tacocat_print_error_on_file(fl_print_t * const print, const f_string_t function, f_string_static_t on, const f_string_static_t network, const f_status_t status, const f_string_static_t name, const f_string_static_t operation) { +#ifndef _di_kt_tacocat_print_error_on_file_receive_ + f_status_t kt_tacocat_print_error_on_file_receive(fl_print_t * const print, const f_string_t function, f_string_static_t on, const f_string_static_t network, const f_status_t status, const f_string_static_t name, const f_string_static_t operation) { + + if (!print || !print->custom) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QNetwork on%] ", print->to, print->set->error, print->prefix, print->set->error); + fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, on, print->set->notable); + fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error, f_string_eol_s); + fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, network, print->set->notable); + fl_print_format("%[' failed to receive data or write to file '%]", print->to, print->set->error, print->set->error, f_string_eol_s); + fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, name, print->set->notable); + fl_print_format("%['.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); + + f_file_stream_unlock(print->to); + + fll_error_file_print(print, F_status_set_fine(((kt_tacocat_main_t *) print->custom)->setting.state.status), function, F_true, name, operation, fll_error_file_type_file_e); + } +#endif // _di_kt_tacocat_print_error_on_file_receive_ + +#ifndef _di_kt_tacocat_print_error_on_file_send_ + f_status_t kt_tacocat_print_error_on_file_send(fl_print_t * const print, const f_string_t function, f_string_static_t on, const f_string_static_t network, const f_status_t status, const f_string_static_t name, const f_string_static_t operation) { if (!print || !print->custom) return F_status_set_error(F_output_not); if (print->verbosity < f_console_verbosity_error_e) return F_output_not; @@ -118,7 +166,7 @@ extern "C" { fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, on, print->set->notable); fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error, f_string_eol_s); fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, network, print->set->notable); - fl_print_format("%[' failed to write to file '%]", print->to, print->set->error, print->set->error, f_string_eol_s); + fl_print_format("%[' failed to send data or read from file '%]", print->to, print->set->error, print->set->error, f_string_eol_s); fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, name, print->set->notable); fl_print_format("%['.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); @@ -126,7 +174,7 @@ extern "C" { fll_error_file_print(print, F_status_set_fine(((kt_tacocat_main_t *) print->custom)->setting.state.status), function, F_true, name, operation, fll_error_file_type_file_e); } -#endif // _di_kt_tacocat_print_error_on_file_ +#endif // _di_kt_tacocat_print_error_on_file_send_ #ifndef _di_kt_tacocat_print_error_on_packet_too_small_ f_status_t kt_tacocat_print_error_on_packet_too_small(fl_print_t * const print, f_string_static_t on, const f_string_static_t network, const f_number_unsigned_t size_expect, const f_number_unsigned_t size_got) { diff --git a/sources/c/tacocat/main/print/error.h b/sources/c/tacocat/main/print/error.h index 7c6695b..bdd5244 100644 --- a/sources/c/tacocat/main/print/error.h +++ b/sources/c/tacocat/main/print/error.h @@ -153,6 +153,36 @@ extern "C" { #endif // _di_kt_tacocat_print_error_on_buffer_too_large_ /** + * Print network-related error message for when file is too large to send. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param file + * The name of the file. + * @param on + * The network connection direction, which should either be "receive" or "send". + * @param network + * The name of the network in which the error is related. + * @param size_max + * The maximum buffer size. + * @param size_got + * The provided buffer size. + * + * @return + * F_okay on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + * + * @see fll_error_file_print() + */ +#ifndef _di_kt_tacocat_print_error_on_file_too_large_ + extern f_status_t kt_tacocat_print_error_on_file_too_large(fl_print_t * const print, f_string_static_t file, f_string_static_t on, const f_string_static_t network, const f_number_unsigned_t size_expect, const f_number_unsigned_t size_got); +#endif // _di_kt_tacocat_print_error_on_file_too_large_ + +/** * Print network-related error message for when the connection is busy. * * @param print @@ -175,8 +205,42 @@ extern "C" { #ifndef _di_kt_tacocat_print_error_on_busy_ extern f_status_t kt_tacocat_print_error_on_busy(fl_print_t * const print, f_string_static_t on, const f_string_static_t network); #endif // _di_kt_tacocat_print_error_on_busy_ + +/** + * Print network-related error message regarding receiving the network data or writing the network data to a file. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param function + * The name of the function where the error happened. + * Set to 0 to disable. + * @param on + * The network connection direction, which should either be "receive" or "send". + * @param network + * The name of the network in which the error is related. + * @param status + * The status code representing the error. + * @param name + * The name of the file or directory. + * @param operation + * The file operation that fails, such as 'open' or 'write'. + * + * @return + * F_okay on success. + * F_output_not on success, but no printing is performed. + * + * F_output_not (with error bit) if setting is NULL. + * + * @see fll_error_file_print() + */ +#ifndef _di_kt_tacocat_print_error_on_file_receive_ + extern f_status_t kt_tacocat_print_error_on_file_receive(fl_print_t * const print, const f_string_t function, f_string_static_t on, const f_string_static_t network, const f_status_t status, const f_string_static_t name, const f_string_static_t operation); +#endif // _di_kt_tacocat_print_error_on_file_receive_ + /** - * Print network-related error message regarding the writing the network data to a file. + * Print network-related error message regarding sending to the network data or reading the file. * * @param print * The output structure to print to. @@ -204,9 +268,9 @@ extern "C" { * * @see fll_error_file_print() */ -#ifndef _di_kt_tacocat_print_error_on_file_ - extern f_status_t kt_tacocat_print_error_on_file(fl_print_t * const print, const f_string_t function, f_string_static_t on, const f_string_static_t network, const f_status_t status, const f_string_static_t name, const f_string_static_t operation); -#endif // _di_kt_tacocat_print_error_on_file_ +#ifndef _di_kt_tacocat_print_error_on_file_send_ + extern f_status_t kt_tacocat_print_error_on_file_send(fl_print_t * const print, const f_string_t function, f_string_static_t on, const f_string_static_t network, const f_status_t status, const f_string_static_t name, const f_string_static_t operation); +#endif // _di_kt_tacocat_print_error_on_file_send_ /** * Print network-related error message for when the connection is busy. diff --git a/sources/c/tacocat/main/receive.c b/sources/c/tacocat/main/receive.c index 10a138c..3a0fd38 100644 --- a/sources/c/tacocat/main/receive.c +++ b/sources/c/tacocat/main/receive.c @@ -74,7 +74,7 @@ extern "C" { set->status = f_file_open(set->name, F_file_mode_all_rw_d, &set->file); if (F_status_is_error(set->status)) { - kt_tacocat_print_error_on_file(&main->program.error, macro_kt_tacocat_f(f_file_open), kt_tacocat_receive_s, set->network, set->status, set->name, f_file_operation_open_s); + kt_tacocat_print_error_on_file_receive(&main->program.error, macro_kt_tacocat_f(f_file_open), kt_tacocat_receive_s, set->network, set->status, set->name, f_file_operation_open_s); return; } @@ -118,7 +118,7 @@ extern "C" { // Keep going on error, but in the future more advanced error handling/recovery is needed to make this more robust. if (F_status_is_error(set->status)) { - kt_tacocat_print_error_on_file(&main->program.error, macro_kt_tacocat_f(f_file_write), kt_tacocat_receive_s, set->network, set->status, set->name, f_file_operation_write_s); + kt_tacocat_print_error_on_file_receive(&main->program.error, macro_kt_tacocat_f(f_file_write), kt_tacocat_receive_s, set->network, set->status, set->name, f_file_operation_write_s); } // Reset buffer used and increment counter. diff --git a/sources/c/tacocat/main/send.c b/sources/c/tacocat/main/send.c index eea7da2..7cf24aa 100644 --- a/sources/c/tacocat/main/send.c +++ b/sources/c/tacocat/main/send.c @@ -69,12 +69,60 @@ extern "C" { // @todo this needs a max retries for sending without error, possibly resetting depending on the part (flag). if (!set->flag) { + set->abstruses.used = 0; + set->buffer.used = 0; + set->header.used = 0; + set->headers.used = 0; set->size_done = 0; + // Initialize the default file payload. + set->status = f_memory_array_increase_by(kt_tacocat_packet_headers_d, sizeof(f_string_map_t), (void **) &set->headers.array, &set->headers.used, &set->headers.size); + macro_kt_send_process_handle_error_exit_1(main, f_memory_array_increase_by, set->network, set->status, set->flag); + + set->status = f_memory_array_increase_by(kt_tacocat_packet_prebuffer_d, sizeof(f_char_t), (void **) &set->header.string, &set->header.used, &set->header.size); + macro_kt_send_process_handle_error_exit_1(main, f_memory_array_increase_by, set->network, set->status, set->flag); + + set->status = f_memory_array_increase_by(kt_tacocat_packet_headers_d, sizeof(f_abstruse_map_t), (void **) &set->abstruses.array, &set->abstruses.used, &set->abstruses.size); + macro_kt_send_process_handle_error_exit_1(main, f_memory_array_increase_by, set->network, set->status, set->flag); + + // Make sure the buffer is large enough for the file block reads (including a space for a terminating NULL). + set->status = f_memory_array_increase_by(set->file.size_read + f_fss_payload_object_payload_s.used + f_fss_payload_object_end_s.used + 2, sizeof(f_char_t), (void **) &set->buffer.string, &set->buffer.used, &set->buffer.size); + macro_kt_send_process_handle_error_exit_1(main, f_memory_array_increase_by, set->network, set->status, set->flag); + + // Index 0 is the status. + set->abstruses.array[0].key = f_fss_payload_object_status_s; + set->abstruses.array[0].value.type = f_abstruse_dynamic_e; + set->abstruses.array[0].value.is.a_dynamic = f_status_okay_s; + + // Index 1 is the type. + set->abstruses.array[1].key = f_fss_payload_object_type_s; + set->abstruses.array[1].value.type = f_abstruse_dynamic_e; + set->abstruses.array[1].value.is.a_dynamic = f_file_type_name_file_s; + + // Index 2 is the length. + set->abstruses.array[2].key = f_fss_payload_object_length_s; + set->abstruses.array[2].value.type = f_abstruse_unsigned_e; + set->abstruses.array[2].value.is.a_unsigned = 0; + + // Index 3 is the part. + set->abstruses.array[3].key = f_fss_payload_object_part_s; + set->abstruses.array[3].value.type = f_abstruse_unsigned_e; + set->abstruses.array[3].value.is.a_unsigned = 0; + + // Index 4 is the total (size of file). + set->abstruses.array[4].key = f_fss_payload_object_total_s; + set->abstruses.array[4].value.type = f_abstruse_unsigned_e; + set->abstruses.array[4].value.is.a_unsigned = 0; + + // Index 5 is the name. + set->abstruses.array[5].key = f_fss_payload_object_name_s; + set->abstruses.array[5].value.type = f_abstruse_dynamic_e; + set->abstruses.array[5].value.is.a_dynamic = set->name; + set->status = f_file_open(set->name, F_file_mode_all_r_d, &set->file); if (F_status_is_error(set->status)) { - kt_tacocat_print_error_on_file(&main->program.error, macro_kt_tacocat_f(f_file_open), kt_tacocat_send_s, set->network, set->status, set->name, f_file_operation_open_s); + kt_tacocat_print_error_on_file_receive(&main->program.error, macro_kt_tacocat_f(f_file_open), kt_tacocat_send_s, set->network, set->status, set->name, f_file_operation_open_s); return F_done_not; } @@ -90,28 +138,33 @@ extern "C" { set->status = f_file_size_by_id(set->file, &total); if (F_status_is_error(set->status)) { - kt_tacocat_print_error_on_file(&main->program.error, macro_kt_tacocat_f(f_file_size_by_id), kt_tacocat_send_s, set->network, set->status, set->name, f_file_operation_open_s); + kt_tacocat_print_error_on_file_receive(&main->program.error, macro_kt_tacocat_f(f_file_size_by_id), kt_tacocat_send_s, set->network, set->status, set->name, f_file_operation_open_s); return F_done_not; } - set->size_total = (size_t) total; // @todo there is a size_total, but there is a total packet size and a total payload size. Find a way to distinguish both. + if ((f_number_unsigned_t) total > F_number_t_size_unsigned_d) { + set->status = F_status_set_error(F_too_large); + + kt_tacocat_print_error_on_file_too_large(&main->program.error, set->name, kt_tacocat_send_s, set->network, F_number_t_size_unsigned_d, set->abstruses.array[4].value.is.a_unsigned); + + return F_done_not; + } + + set->abstruses.array[4].value.is.a_unsigned = (f_number_unsigned_t) total; set->flag = kt_tacocat_socket_flag_send_file_e; } if (set->flag == kt_tacocat_socket_flag_send_file_e) { set->buffer.used = 0; - // Make sure the buffer is large enough for the file block reads (including a space for a terminating NULL). - set->status = f_memory_array_increase_by(set->file.size_read + f_fss_payload_object_payload_s.used + f_fss_payload_object_end_s.used + 1, sizeof(f_char_t), (void **) &set->buffer.string, &set->buffer.used, &set->buffer.size); - macro_kt_send_process_handle_error_exit_1(main, f_memory_array_increase_by, set->network, set->status, set->flag); - set->status = f_string_dynamic_append(f_fss_payload_object_payload_s, &set->buffer); macro_kt_send_process_handle_error_exit_1(main, f_file_read_block, set->network, set->status, set->flag); set->status = f_string_dynamic_append(f_fss_payload_object_end_s, &set->buffer); macro_kt_send_process_handle_error_exit_1(main, f_file_read_block, set->network, set->status, set->flag); + // Each block is sent one at a time. set->status = f_file_read_block(set->file, &set->buffer); macro_kt_send_process_handle_error_exit_1(main, f_file_read_block, set->network, set->status, set->flag); @@ -123,10 +176,7 @@ extern "C" { if (set->flag == kt_tacocat_socket_flag_send_build_e) { set->header.used = 0; - if (set->buffer.used) { - set->status = f_memory_array_increase_by(kt_tacocat_packet_prebuffer_d, sizeof(f_char_t), (void **) &set->header.string, &set->header.used, &set->header.size); - macro_kt_send_process_handle_error_exit_1(main, f_memory_array_increase_by, set->network, set->status, set->flag); - + if (set->header.used) { f_state_t state_local = main->setting.state; state_local.data = &set->write_state; @@ -142,7 +192,7 @@ extern "C" { // 1) type file (or string, and if file, then name is filesize and size is filesize, otherwise name is unused and size is string length.) // 1) name "example.csv" // 2) size 1234 - // 3) status F_okay + // 3) status F_okay (f_status_okay_s) // @todo // 1) Build abstruse headers map of data. diff --git a/sources/c/tacocat/main/send.h b/sources/c/tacocat/main/send.h index a243933..42d5a2f 100644 --- a/sources/c/tacocat/main/send.h +++ b/sources/c/tacocat/main/send.h @@ -45,10 +45,13 @@ extern "C" { * * F_packet_too_large (with error bit) on total packet size is too large. * F_payload_too_large (with error bit) on total payload size is too large. + * F_too_large (with error bit) on file too large. * @param set * The socket set to process. * Must not be NULL. * + * @todo Processing and logic around the return status needs to reviewed and updated. + * * @see f_socket_read_stream() */ #ifndef _di_kt_tacocat_send_process_ diff --git a/sources/c/tacocat/main/tacocat.h b/sources/c/tacocat/main/tacocat.h index b0b5dd7..6b83270 100644 --- a/sources/c/tacocat/main/tacocat.h +++ b/sources/c/tacocat/main/tacocat.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include -- 1.8.3.1