From: Kevin Day Date: Sun, 3 Sep 2023 03:43:11 +0000 (-0500) Subject: Progress: Further work in TacocaT. X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=3633aff2cb2ec91766593db8ddee2b115a1952e1;p=kevux-tools Progress: Further work in TacocaT. --- diff --git a/data/build/tacocat/dependencies b/data/build/tacocat/dependencies index 6ffc06e..82111db 100644 --- a/data/build/tacocat/dependencies +++ b/data/build/tacocat/dependencies @@ -19,6 +19,7 @@ f_print f_signal f_socket f_thread +f_time fl_conversion fl_print diff --git a/data/build/tacocat/settings b/data/build/tacocat/settings index 0529397..03921a7 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_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_type_array -lf_utf +build_libraries-individual -lfll_error -lfll_print -lfll_program -lfl_conversion -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_thread -lf_thread build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll diff --git a/sources/c/tacocat/main/common.c b/sources/c/tacocat/main/common.c index cddf62f..a471c97 100644 --- a/sources/c/tacocat/main/common.c +++ b/sources/c/tacocat/main/common.c @@ -188,7 +188,7 @@ extern "C" { } if (number == 0) { - kt_tacocat_print_warning_parameter_integer_is(&main->program.warning, f_console_symbol_long_normal_s, kt_tacocat_long_max_buffer_s, f_string_ascii_0_s); + kt_tacocat_print_warning_parameter_integer_less_than(&main->program.warning, f_console_symbol_long_normal_s, kt_tacocat_long_max_buffer_s, main->program.parameters.arguments.array[index]); main->setting.max_buffer = 0; main->setting.flag |= kt_tacocat_main_flag_max_buffer_e; @@ -309,6 +309,8 @@ extern "C" { sets[i]->statuss.array[j] = F_okay; sets[i]->flags.array[j] = kt_tacocat_socket_flag_none_e; + sets[i]->retrys.array[j] = 0; + sets[i]->totals.array[j] = 0; sets[i]->names.array[j].used = 0; sets[i]->buffers.array[j].used = 0; sets[i]->packets.array[j].control.start = 1; @@ -604,8 +606,10 @@ extern "C" { set->names.used = 0; set->packets.used = 0; set->polls.used = 0; + set->retrys.used = 0; set->sockets.used = 0; set->statuss.used = 0; + set->totals.used = 0; if (!set) { main->setting.state.status = F_status_set_error(F_parameter); @@ -628,6 +632,10 @@ extern "C" { } if (F_status_is_error_not(main->setting.state.status)) { + main->setting.state.status = f_memory_array_increase_by(total, sizeof(uint16_t), (void **) &set->retrys.array, &set->retrys.used, &set->retrys.size); + } + + if (F_status_is_error_not(main->setting.state.status)) { main->setting.state.status = f_memory_array_increase_by(total, sizeof(f_string_dynamic_t), (void **) &set->names.array, &set->names.used, &set->names.size); } @@ -644,6 +652,10 @@ extern "C" { } if (F_status_is_error_not(main->setting.state.status)) { + main->setting.state.status = f_memory_array_increase_by(total, sizeof(uint32_t), (void **) &set->totals.array, &set->totals.used, &set->totals.size); + } + + if (F_status_is_error_not(main->setting.state.status)) { main->setting.state.status = F_okay; } } diff --git a/sources/c/tacocat/main/common/define.h b/sources/c/tacocat/main/common/define.h index 2682fea..232f8ae 100644 --- a/sources/c/tacocat/main/common/define.h +++ b/sources/c/tacocat/main/common/define.h @@ -29,6 +29,9 @@ extern "C" { * - size_receive: The block size in bytes to use when sending packets. * - size_send: The block size in bytes to use when receiving packets. * + * kt_tacocat_cache_*_d: + * - peek: The size in bytes representing the size of the peek cache (should be set to at least "kt_tacocat_block_size_receive_d + 1" and must be greater than zero). + * * kt_tacocat_interval_*_d: * - poll: The time in milliseconds to poll for before returning (this is the amount of time poll() blocks). * @@ -44,15 +47,22 @@ extern "C" { * kt_tacocat_signal_*_d: * - check: When not using threads, this is how often to perform the check (lower numbers incur more kernel I/O). * - check_failsafe: When using threads, how many consecutive failures to check signal before aborting (as a recursion failsafe). + * + * kt_tacocat_startup_*_d: + * - retry_delay_second: The delay in seconds to wait between each retry. + * - retry_delay_millisecond: The delay in milliseconds to wait between each retry. + * - retry_max: During start up, the maximum number of retries to perform when trying to establish the initial connection before giving up. */ #ifndef _di_kt_tacocat_d_ #define kt_tacocat_allocation_console_d 0x4 #define kt_tacocat_allocation_large_d 0x800 #define kt_tacocat_allocation_small_d 0x80 - #define kt_tacocat_block_size_d 0xffff - #define kt_tacocat_block_size_receive_d kt_tacocat_block_size_d - #define kt_tacocat_block_size_send_d kt_tacocat_block_size_d + #define kt_tacocat_block_size_d 0xffff + #define kt_tacocat_block_size_receive_d kt_tacocat_block_size_d + #define kt_tacocat_block_size_send_d kt_tacocat_block_size_d + + #define kt_tacocat_cache_size_peek_d (kt_tacocat_block_size_receive_d + 1) #define kt_tacocat_interval_poll_d 1400 // 1.4 second. @@ -65,6 +75,10 @@ extern "C" { #define kt_tacocat_signal_check_d 0x4e20 #define kt_tacocat_signal_check_failsafe_d 0x4e20 + + #define kt_tacocat_startup_retry_delay_second_d 3 + #define kt_tacocat_startup_retry_delay_millisecond_d 0 + #define kt_tacocat_startup_retry_max_d 24 #endif // _di_kt_tacocat_d_ /** @@ -79,6 +93,14 @@ extern "C" { * * macro_setting_load_handle_send_receive_error_file_continue_1: * The same as macro_setting_load_handle_send_receive_error_continue_1() but intended for file errors. + * + * macro_kt_receive_process_handle_error_exit_1: + * Intended to be used for handling an error during the receive process while processing within flag kt_tacocat_socket_flag_block_begin_e. + * The parameter id_data and is set to 0 to disable and is otherwise an address pointer. + * + * macro_kt_receive_process_handle_error_exit_2: + * Intended to be used for handling an error during the receive process while not processing within flag kt_tacocat_socket_flag_block_begin_e. + * The parameter id_data and is set to 0 to disable and is otherwise an address pointer. */ #ifndef _di_kt_tacocat_macros_d_ #define macro_setting_load_print_first() \ @@ -128,6 +150,36 @@ extern "C" { \ continue; \ } + + // @todo handle error, perform memory clearing and possibly send try again message to client but for now, just close the connection gracefully. + #define macro_kt_receive_process_handle_error_exit_1(main, method, name, status, flag, id_data) \ + if (F_status_is_error(*status)) { \ + kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(method), kt_tacocat_receive_s, *name, *status); \ + \ + if (id_data) { \ + f_file_close_id(id_data); \ + } \ + \ + *flag -= kt_tacocat_socket_flag_block_begin_e; \ + \ + return; \ + } + + // @todo handle error, perform memory clearing and possibly send try again message to client but for now, just close the connection gracefully. + #define macro_kt_receive_process_handle_error_exit_2(main, method, name, status, flag, id_data) \ + if (F_status_is_error(*status)) { \ + kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(method), kt_tacocat_receive_s, *name, *status); \ + \ + if (id_data) { \ + f_file_close_id(id_data); \ + } \ + \ + *flag -= *flag & kt_tacocat_socket_flag_block_begin_e; \ + *flag -= *flag & kt_tacocat_socket_flag_block_control_e; \ + *flag -= *flag & kt_tacocat_socket_flag_block_payload_e; \ + \ + return; \ + } #endif // _di_kt_tacocat_macro_d_ #ifdef __cplusplus diff --git a/sources/c/tacocat/main/common/enumeration.h b/sources/c/tacocat/main/common/enumeration.h index a7b6537..eee8aa6 100644 --- a/sources/c/tacocat/main/common/enumeration.h +++ b/sources/c/tacocat/main/common/enumeration.h @@ -131,14 +131,16 @@ extern "C" { * * kt_tacocat_socket_flag_*_e: * - none: No flags set. + * - block_begin: The control block is ready to be read (but has not been fully ready yet). * - block_control: The control block is fully read. * - block_payload: The payload block is fully read. */ #ifndef _di_kt_tacocat_socket_flag_e_ enum { kt_tacocat_socket_flag_none_e = 0x0, - kt_tacocat_socket_flag_block_control_e = 0x1, - kt_tacocat_socket_flag_block_payload_e = 0x2, + kt_tacocat_socket_flag_block_begin_e = 0x1, + kt_tacocat_socket_flag_block_control_e = 0x2, + kt_tacocat_socket_flag_block_payload_e = 0x4, }; // enum #endif // _di_kt_tacocat_socket_flag_e_ diff --git a/sources/c/tacocat/main/common/print.c b/sources/c/tacocat/main/common/print.c index eed3717..6553719 100644 --- a/sources/c/tacocat/main/common/print.c +++ b/sources/c/tacocat/main/common/print.c @@ -7,6 +7,7 @@ extern "C" { #ifndef _di_kt_tacocat_f_a_ const f_string_t kt_tacocat_f_a[] = { "f_console_parameter_process", + "f_file_close_id", "f_file_open", "f_fss_simple_packet_identify", "f_memory_array_increase_by", @@ -21,11 +22,13 @@ extern "C" { "f_socket_create", "f_socket_disconnect", "f_socket_listen", + "f_socket_option_set", "f_socket_read_stream", "f_string_append_nulless", "f_string_dynamic_append", "f_string_dynamic_append_nulless", "f_thread_create", + "fl_conversion_dynamic_partial_to_unsigned_detect", "fl_conversion_dynamic_to_unsigned_detect", "fll_program_parameter_process_context", "fll_program_parameter_process_verbosity", diff --git a/sources/c/tacocat/main/common/print.h b/sources/c/tacocat/main/common/print.h index 2f11935..b1a4e30 100644 --- a/sources/c/tacocat/main/common/print.h +++ b/sources/c/tacocat/main/common/print.h @@ -40,6 +40,7 @@ extern "C" { #ifndef _di_kt_tacocat_f_e_ enum { kt_tacocat_f_f_console_parameter_process_e, + kt_tacocat_f_f_file_close_id_e, kt_tacocat_f_f_file_open_e, kt_tacocat_f_f_fss_simple_packet_identify_e, kt_tacocat_f_f_memory_array_increase_by_e, @@ -54,11 +55,13 @@ extern "C" { kt_tacocat_f_f_socket_create_e, kt_tacocat_f_f_socket_disconnect_e, kt_tacocat_f_f_socket_listen_e, + kt_tacocat_f_f_socket_option_set_e, kt_tacocat_f_f_socket_read_stream_e, kt_tacocat_f_f_string_append_nulless_e, kt_tacocat_f_f_string_dynamic_append_e, kt_tacocat_f_f_string_dynamic_append_nulless_e, kt_tacocat_f_f_thread_create_e, + kt_tacocat_f_fl_conversion_dynamic_partial_to_unsigned_detect_e, kt_tacocat_f_fl_conversion_dynamic_to_unsigned_detect_e, kt_tacocat_f_fll_program_parameter_process_context_e, kt_tacocat_f_fll_program_parameter_process_verbosity_e, diff --git a/sources/c/tacocat/main/common/type.c b/sources/c/tacocat/main/common/type.c index 7e55f03..c20ef66 100644 --- a/sources/c/tacocat/main/common/type.c +++ b/sources/c/tacocat/main/common/type.c @@ -35,10 +35,15 @@ extern "C" { } // for for (j = 0; j < sets[i]->sockets.used ; ++j) { + + f_file_close_id(&sets[i]->sockets.array[j].id_data); + f_socket_disconnect(&sets[i]->sockets.array[j], program.signal_received ? f_socket_close_fast_e : f_socket_close_read_write_e); } // for f_memory_array_resize(0, sizeof(uint16_t), (void **) &sets[i]->flags.array, &sets[i]->flags.used, &sets[i]->flags.size); + f_memory_array_resize(0, sizeof(uint16_t), (void **) &sets[i]->retrys.array, &sets[i]->retrys.used, &sets[i]->retrys.size); + f_memory_array_resize(0, sizeof(uint32_t), (void **) &sets[i]->totals.array, &sets[i]->totals.used, &sets[i]->totals.size); f_memory_array_resize(0, sizeof(f_file_t), (void **) &sets[i]->files.array, &sets[i]->files.used, &sets[i]->files.size); f_memory_array_resize(0, sizeof(f_poll_t), (void **) &sets[i]->polls.array, &sets[i]->polls.used, &sets[i]->polls.size); f_memory_array_resize(0, sizeof(f_socket_t), (void **) &sets[i]->sockets.array, &sets[i]->sockets.used, &sets[i]->sockets.size); diff --git a/sources/c/tacocat/main/common/type.h b/sources/c/tacocat/main/common/type.h index 76fbdcb..fe8da64 100644 --- a/sources/c/tacocat/main/common/type.h +++ b/sources/c/tacocat/main/common/type.h @@ -23,6 +23,8 @@ extern "C" { * max_buffer: The maximum size in bytes to used to represent a block when sending or receiving packets. * * flags: An array of flags for each socket. + * retrys: An array of the current number of retries performed for the given network packet. + * totals: An array of the total network stream size accoding to the processed packet. * files: An array of files for each socket. * polls: An array of sockets to poll, specifically for passing to f_file_poll(). * sockets: An array of the network sockets. @@ -37,6 +39,8 @@ extern "C" { f_number_unsigned_t size_block; f_uint16s_t flags; + f_uint16s_t retrys; + f_uint32s_t totals; f_files_t files; f_polls_t polls; f_sockets_t sockets; @@ -51,6 +55,8 @@ extern "C" { { \ kt_tacocat_block_size_d, \ f_uint16s_t_initialize, \ + f_uint16s_t_initialize, \ + f_uint32s_t_initialize, \ f_files_t_initialize, \ f_polls_t_initialize, \ f_sockets_t_initialize, \ @@ -64,6 +70,8 @@ extern "C" { { \ size_block, \ f_uint16s_t_initialize, \ + f_uint16s_t_initialize, \ + f_uint32s_t_initialize, \ f_files_t_initialize, \ f_polls_t_initialize, \ f_sockets_t_initialize, \ @@ -129,6 +137,22 @@ extern "C" { #endif // _di_kt_tacocat_setting_t_ /** + * The TacocaT caches. + * + * peek: A static cache intended to be used for performing a peek on a given network stream. + */ +#ifndef _di_kt_tacocat_cache_t_ + typedef struct { + f_char_t peek[kt_tacocat_cache_size_peek_d]; + } kt_tacocat_cache_t; + + #define kt_tacocat_cache_t_initialize \ + { \ + { 0 }, \ + } +#endif // _di_kt_tacocat_cache_t_ + +/** * The TacocaT callbacks. * * setting_load_send_receive: Process loading the settings regarding send and receive, handling DNS resolution and file opening as needed. @@ -174,6 +198,7 @@ extern "C" { kt_tacocat_setting_t setting; kt_tacocat_callback_t callback; kt_tacocat_thread_t thread; + kt_tacocat_cache_t cache; } kt_tacocat_main_t; #define kt_tacocat_main_t_initialize \ @@ -182,6 +207,7 @@ extern "C" { kt_tacocat_setting_t_initialize, \ kt_tacocat_callback_t_initialize, \ kt_tacocat_thread_t_initialize, \ + kt_tacocat_cache_t_initialize, \ } #endif // _di_kt_tacocat_main_t_ diff --git a/sources/c/tacocat/main/print/error.c b/sources/c/tacocat/main/print/error.c index 595fe9f..a759af7 100644 --- a/sources/c/tacocat/main/print/error.c +++ b/sources/c/tacocat/main/print/error.c @@ -16,6 +16,18 @@ extern "C" { } #endif // _di_kt_tacocat_print_error_ +#ifndef _di_kt_tacocat_print_error_status_ + f_status_t kt_tacocat_print_error_status(fl_print_t * const print, const f_string_t function, const f_status_t status) { + + if (!print) return F_status_set_error(F_output_not); + if (print->verbosity < f_console_verbosity_error_e) return F_output_not; + + fll_error_print(print, F_status_set_fine(status), function, F_true); + + return F_okay; + } +#endif // _di_kt_tacocat_print_error_status_ + #ifndef _di_kt_tacocat_print_error_file_ f_status_t kt_tacocat_print_error_file(fl_print_t * const print, const f_string_t function, const f_string_static_t name, const f_string_static_t operation, const uint8_t type) { @@ -31,7 +43,7 @@ extern "C" { #ifndef _di_kt_tacocat_print_error_on_ f_status_t kt_tacocat_print_error_on(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) { - if (!print || !print->custom) return F_status_set_error(F_output_not); + 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); @@ -53,7 +65,7 @@ extern "C" { #ifndef _di_kt_tacocat_print_error_on_buffer_too_large_ f_status_t kt_tacocat_print_error_on_buffer_too_large(fl_print_t * const print, f_string_static_t on, const f_string_static_t network) { - if (!print || !print->custom) return F_status_set_error(F_output_not); + 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); @@ -70,6 +82,50 @@ extern "C" { } #endif // _di_kt_tacocat_print_error_on_buffer_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) { + + 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("%[%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("%[' is busy.%]%r", 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_busy_ + +#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) { + + 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("%[%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("%[', the received packet is too small (expecting%] ", 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(" %[bytes but instead got%] ", print->to, print->set->error, print->set->error, f_string_eol_s); + fl_print_format("%[%ul%]", print->to, print->set->notable, size_got, print->set->notable); + fl_print_format("%[ bytes).%]%r", 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_packet_too_small_ + #ifndef _di_kt_tacocat_print_error_parameter_value_resolve_unknown_ f_status_t kt_tacocat_print_error_parameter_value_resolve_unknown(fl_print_t * const print, const f_string_dynamic_t unknown) { diff --git a/sources/c/tacocat/main/print/error.h b/sources/c/tacocat/main/print/error.h index 18f3613..0800437 100644 --- a/sources/c/tacocat/main/print/error.h +++ b/sources/c/tacocat/main/print/error.h @@ -22,7 +22,11 @@ extern "C" { * @param print * The output structure to print to. * + * This requires print.custom to be fake_main_t. + * * This does not alter print.custom.setting.state.status. + * @param function + * A string representing the function that has an error. * * @return * F_okay on success. @@ -37,11 +41,37 @@ extern "C" { #endif // _di_kt_tacocat_print_error_ /** + * Print generic error message regarding a function failing in some way using the given status. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @param function + * A string representing the function that has an error. + * @param status + * The status code representing the error being reported. + * + * @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_print() + */ +#ifndef _di_kt_tacocat_print_error_status_ + extern f_status_t kt_tacocat_print_error_status(fl_print_t * const print, const f_string_t function, const f_status_t status); +#endif // _di_kt_tacocat_print_error_status_ + +/** * Print file related error or warning messages. * * @param print * The output structure to print to. * + * This requires print.custom to be fake_main_t. + * * This does not alter print.custom.setting.state.status. * @param function * The name of the function where the error happened. @@ -66,7 +96,7 @@ extern "C" { #endif // _di_kt_tacocat_print_error_file_ /** - * Print file related error or warning messages. + * Print network-related error message regarding a function failing in some way using the given status. * * @param print * The output structure to print to. @@ -91,11 +121,11 @@ extern "C" { * @see fll_error_file_print() */ #ifndef _di_kt_tacocat_print_error_on_ - f_status_t kt_tacocat_print_error_on(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); + extern f_status_t kt_tacocat_print_error_on(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); #endif // _di_kt_tacocat_print_error_on_ /** - * Print file related error or warning messages for when buffer is too large to accept additional packet blocks. + * Print network-related error message for when buffer is too large to accept additional packet blocks. * * @param print * The output structure to print to. @@ -115,10 +145,62 @@ extern "C" { * @see fll_error_file_print() */ #ifndef _di_kt_tacocat_print_error_on_buffer_too_large_ - f_status_t kt_tacocat_print_error_on_buffer_too_large(fl_print_t * const print, f_string_static_t on, const f_string_static_t network); + extern f_status_t kt_tacocat_print_error_on_buffer_too_large(fl_print_t * const print, f_string_static_t on, const f_string_static_t network); #endif // _di_kt_tacocat_print_error_on_buffer_too_large_ /** + * Print network-related error message for when the connection is busy. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @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. + * + * @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_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 for when the connection is busy. + * + * @param print + * The output structure to print to. + * + * This does not alter print.custom.setting.state.status. + * @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_expect + * The expected packet size. + * @param size_got + * The packet size that is received. + * + * @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_packet_too_small_ + extern 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); +#endif // _di_kt_tacocat_print_error_on_packet_too_small_ + +/** * Print error message for when an unknown value for the resolve parameter is provided. * * @param print @@ -146,6 +228,8 @@ extern "C" { * @param print * The output structure to print to. * + * This requires print.custom to be fake_main_t. + * * This does not alter print.custom.setting.state.status. * @param address * The entire address string, including the port number. diff --git a/sources/c/tacocat/main/print/warning.c b/sources/c/tacocat/main/print/warning.c index 3e3b16e..3efd5f1 100644 --- a/sources/c/tacocat/main/print/warning.c +++ b/sources/c/tacocat/main/print/warning.c @@ -4,24 +4,45 @@ extern "C" { #endif -#ifndef _di_kt_tacocat_print_warning_parameter_integer_is_ - f_status_t kt_tacocat_print_warning_parameter_integer_is(fl_print_t * const print, const f_string_static_t symbol, const f_string_static_t name, const f_string_static_t is) { +#ifndef _di_kt_tacocat_print_warning_on_busy_ + f_status_t kt_tacocat_print_warning_on_busy(fl_print_t * const print, f_string_static_t on, const f_string_static_t network, const f_number_unsigned_t retry) { if (print->verbosity < f_console_verbosity_verbose_e) return F_output_not; f_file_stream_lock(print->to); - fl_print_format("%[%QThe value for the parameter '%]", print->to, print->set->error, print->set->error); + fl_print_format("%[%QNetwork on%] ", print->to, print->context, print->prefix, print->context); + 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->context, print->context, 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("%[' is busy, pausing and then retrying %ul/%ul.%]%r", print->to, print->context, retry, kt_tacocat_startup_retry_max_d, print->context, f_string_eol_s); + + f_file_stream_unlock(print->to); + + return F_okay; + } +#endif // _di_kt_tacocat_print_warning_on_busy_ + +#ifndef _di_kt_tacocat_print_warning_parameter_integer_less_than_ + f_status_t kt_tacocat_print_warning_parameter_integer_less_than(fl_print_t * const print, const f_string_static_t symbol, const f_string_static_t name, const f_string_static_t is) { + + if (print->verbosity < f_console_verbosity_verbose_e) return F_output_not; + + f_file_stream_lock(print->to); + + fl_print_format("%[%QThe value '%]", print->to, print->context, print->context); + fl_print_format(f_string_format_QQ_single_s.string, print->to, print->set->notable, is, print->set->notable); + fl_print_format("%[' for the parameter '%]", print->to, print->context, print->context); fl_print_format(f_string_format_QQ_single_s.string, print->to, print->set->notable, symbol, name, print->set->notable); - fl_print_format("%[' is %]", print->to, print->set->error, print->set->error); - fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, is, 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); + fl_print_format("%[' is less than %]", print->to, print->context, print->context); + fl_print_format("%[%ul%]", print->to, print->notable, kt_tacocat_packet_peek_d, print->notable); + fl_print_format(f_string_format_sentence_end_s.string, print->to, print->context, print->context, f_string_eol_s); f_file_stream_unlock(print->to); return F_okay; } -#endif // _di_kt_tacocat_print_warning_parameter_integer_is_ +#endif // _di_kt_tacocat_print_warning_parameter_integer_less_than_ #ifndef _di_kt_tacocat_print_warning_port_number_overflow_ f_status_t kt_tacocat_print_warning_port_number_overflow(fl_print_t * const print, const f_string_static_t address, const f_number_unsigned_t port) { diff --git a/sources/c/tacocat/main/print/warning.h b/sources/c/tacocat/main/print/warning.h index a4ed861..9b9b632 100644 --- a/sources/c/tacocat/main/print/warning.h +++ b/sources/c/tacocat/main/print/warning.h @@ -17,12 +17,37 @@ extern "C" { #endif /** - * Print warning message about given parameter being a specific integer value. + * Print warning message about given port number being out of range for this system. + * Print file related error or warning messages. * * @param print * The output structure to print to. * - * This requires print.custom to be fake_main_t. + * This does not alter print.custom.setting.state.status. + * @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 retry + * The current retry attempt. + * + * @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_warning_on_busy_ + extern f_status_t kt_tacocat_print_warning_on_busy(fl_print_t * const print, f_string_static_t on, const f_string_static_t network, const f_number_unsigned_t retry); +#endif // _di_kt_tacocat_print_warning_on_busy_ + +/** + * Print warning message about given parameter being a specific integer value. + * + * @param print + * The output structure to print to. * * This does not alter print.custom.setting.state.status. * @param symbol @@ -44,9 +69,9 @@ extern "C" { * @see f_file_stream_unlock() * @see fl_print_format() */ -#ifndef _di_kt_tacocat_print_warning_parameter_integer_is_ - extern f_status_t kt_tacocat_print_warning_parameter_integer_is(fl_print_t * const print, const f_string_static_t symbol, const f_string_static_t name, const f_string_static_t is); -#endif // _di_kt_tacocat_print_warning_parameter_integer_is_ +#ifndef _di_kt_tacocat_print_warning_parameter_integer_less_than_ + extern f_status_t kt_tacocat_print_warning_parameter_integer_less_than(fl_print_t * const print, const f_string_static_t symbol, const f_string_static_t name, const f_string_static_t than); +#endif // _di_kt_tacocat_print_warning_parameter_integer_less_than_ /** * Print warning message about given port number being out of range for this system. @@ -54,8 +79,6 @@ extern "C" { * @param print * The output structure to print to. * - * This requires print.custom to be fake_main_t. - * * This does not alter print.custom.setting.state.status. * @param address * The original address string. diff --git a/sources/c/tacocat/main/process.c b/sources/c/tacocat/main/process.c index 2748b3a..68ab129 100644 --- a/sources/c/tacocat/main/process.c +++ b/sources/c/tacocat/main/process.c @@ -72,12 +72,20 @@ extern "C" { if (kt_tacocat_signal_check(main)) return F_status_set_error(F_interrupt); + status = f_file_close_id(&set->sockets.array[i].id_data); + + if (F_status_is_error_not(set->statuss.array[i]) && F_status_is_error(status)) { + set->statuss.array[i] = status; + + kt_tacocat_print_error_status(&main->program.error, macro_kt_tacocat_f(f_file_close_id), status); + } + status = f_socket_disconnect(&set->sockets.array[i], f_socket_close_read_write_e); if (F_status_is_error_not(set->statuss.array[i]) && F_status_is_error(status)) { set->statuss.array[i] = status; - kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_socket_disconnect)); + kt_tacocat_print_error_status(&main->program.error, macro_kt_tacocat_f(f_socket_disconnect), status); } } // for @@ -114,7 +122,7 @@ extern "C" { *status = F_status_set_error(F_parameter); } - kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(kt_tacocat_process_socket_set_error_has)); + kt_tacocat_print_error_status(&main->program.error, macro_kt_tacocat_f(kt_tacocat_process_socket_set_error_has), *status); return F_status_set_error(F_parameter); } @@ -136,6 +144,8 @@ extern "C" { if (!main || F_status_is_error(main->setting.status_receive)) return; + int value_socket = 0; + for (f_number_unsigned_t i = 0; i < main->setting.receive.sockets.used; ++i) { if (kt_tacocat_signal_check(main)) return; @@ -146,37 +156,93 @@ extern "C" { if (F_status_is_error(main->setting.receive.statuss.array[i])) { main->setting.status_receive = main->setting.receive.statuss.array[i]; - kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_socket_create)); + kt_tacocat_print_error_status(&main->program.error, macro_kt_tacocat_f(f_socket_create), main->setting.status_receive); continue; } - if (main->setting.receive.sockets.array[i].domain == f_socket_protocol_family_inet4_e) { - main->setting.receive.statuss.array[i] = f_socket_bind_inet4(&main->setting.receive.sockets.array[i]); - } - else if (main->setting.receive.sockets.array[i].domain == f_socket_protocol_family_inet6_e) { - main->setting.receive.statuss.array[i] = f_socket_bind_inet6(&main->setting.receive.sockets.array[i]); - } - else if (main->setting.receive.sockets.array[i].domain == f_socket_protocol_family_local_e) { - main->setting.receive.statuss.array[i] = f_socket_bind_local(&main->setting.receive.sockets.array[i]); + // Make the socket re-usable. + { + value_socket = 1; + + main->setting.receive.statuss.array[i] = f_socket_option_set(&main->setting.receive.sockets.array[i], SOL_SOCKET, f_socket_option_address_reuse_e | f_socket_option_port_reuse_e, &value_socket, sizeof(int)); + + if (F_status_is_error(main->setting.receive.statuss.array[i])) { + main->setting.status_receive = main->setting.receive.statuss.array[i]; + + kt_tacocat_print_error_status(&main->program.error, macro_kt_tacocat_f(f_socket_option_set), main->setting.status_receive); + + continue; + } } - else { - main->setting.status_receive = F_status_set_error(F_parameter); - kt_tacocat_print_error_socket_protocol_unsupported(&main->program.error, main->setting.receive.names.array[i], main->setting.receive.sockets.array[i].domain); + for (main->setting.receive.retrys.array[i] = 0; main->setting.receive.retrys.array[i] < kt_tacocat_startup_retry_max_d; ++main->setting.receive.retrys.array[i]) { - return; + if (main->setting.receive.sockets.array[i].domain == f_socket_protocol_family_inet4_e) { + main->setting.receive.statuss.array[i] = f_socket_bind_inet4(&main->setting.receive.sockets.array[i]); + } + else if (main->setting.receive.sockets.array[i].domain == f_socket_protocol_family_inet6_e) { + main->setting.receive.statuss.array[i] = f_socket_bind_inet6(&main->setting.receive.sockets.array[i]); + } + else if (main->setting.receive.sockets.array[i].domain == f_socket_protocol_family_local_e) { + main->setting.receive.statuss.array[i] = f_socket_bind_local(&main->setting.receive.sockets.array[i]); + } + else { + main->setting.status_receive = F_status_set_error(F_parameter); + + kt_tacocat_print_error_socket_protocol_unsupported(&main->program.error, main->setting.receive.names.array[i], main->setting.receive.sockets.array[i].domain); + + return; + } + + if (F_status_set_fine(main->setting.receive.statuss.array[i]) == F_busy_address) { + if (main->setting.receive.retrys.array[i] < kt_tacocat_startup_retry_max_d) { + kt_tacocat_print_warning_on_busy(&main->program.warning, kt_tacocat_receive_s, main->setting.receive.names.array[i], main->setting.receive.retrys.array[i] + 1); + + struct timespec time = { 0 }; + + main->setting.receive.statuss.array[i] = f_time_spec_millisecond(kt_tacocat_startup_retry_delay_second_d, kt_tacocat_startup_retry_delay_millisecond_d, &time); + + if (F_status_is_error_not(main->setting.receive.statuss.array[i])) { + nanosleep(&time, 0); + } + + if (main->program.signal_received) { + main->setting.status_receive = F_status_set_error(F_interrupt); + + return; + } + + main->setting.receive.statuss.array[i] = F_status_set_error(F_busy_address); + + continue; + } + } + + break; + } // for + + if (F_status_is_error_not(main->setting.receive.statuss.array[i]) && main->setting.receive.retrys.array[i] < kt_tacocat_startup_retry_max_d) { + main->setting.receive.statuss.array[i] = F_okay; } + main->setting.receive.retrys.array[i] = 0; + if (F_status_is_error(main->setting.receive.statuss.array[i])) { main->setting.status_receive = main->setting.receive.statuss.array[i]; - kt_tacocat_print_error(&main->program.error, main->setting.receive.sockets.array[i].domain == f_socket_protocol_family_inet4_e - ? macro_kt_tacocat_f(f_socket_bind_inet4) - : main->setting.receive.sockets.array[i].domain == f_socket_protocol_family_inet6_e - ? macro_kt_tacocat_f(f_socket_bind_inet6) - : macro_kt_tacocat_f(f_socket_bind_local) - ); + if (F_status_set_fine(main->setting.status_receive) == F_busy_address) { + kt_tacocat_print_error_on_busy(&main->program.error, kt_tacocat_receive_s, main->setting.receive.names.array[i]); + } + else { + kt_tacocat_print_error_status(&main->program.error, main->setting.receive.sockets.array[i].domain == f_socket_protocol_family_inet4_e + ? macro_kt_tacocat_f(f_socket_bind_inet4) + : main->setting.receive.sockets.array[i].domain == f_socket_protocol_family_inet6_e + ? macro_kt_tacocat_f(f_socket_bind_inet6) + : macro_kt_tacocat_f(f_socket_bind_local), + main->setting.status_receive + ); + } continue; } @@ -186,7 +252,7 @@ extern "C" { if (F_status_is_error(main->setting.receive.statuss.array[i])) { main->setting.status_receive = main->setting.receive.statuss.array[i]; - kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_socket_listen)); + kt_tacocat_print_error_status(&main->program.error, macro_kt_tacocat_f(f_socket_listen), main->setting.status_receive); continue; } @@ -224,7 +290,7 @@ extern "C" { if (F_status_is_error(main->setting.send.statuss.array[i])) { main->setting.status_send = main->setting.send.statuss.array[i]; - kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_socket_create)); + kt_tacocat_print_error_status(&main->program.error, macro_kt_tacocat_f(f_socket_create), main->setting.status_send); continue; } diff --git a/sources/c/tacocat/main/receive.c b/sources/c/tacocat/main/receive.c index fe3841a..29f2be2 100644 --- a/sources/c/tacocat/main/receive.c +++ b/sources/c/tacocat/main/receive.c @@ -32,8 +32,7 @@ extern "C" { if (main->setting.receive.polls.array[i].fd == -1) continue; - // @todo figure out what f_poll_urgent_e can be. - if (main->setting.receive.polls.array[i].revents & (f_poll_read_e | f_poll_urgent_e)) { + if (main->setting.receive.polls.array[i].revents & (f_poll_read_e)) { kt_tacocat_receive_process(main, i); main->setting.receive.polls.array[i].revents = 0; @@ -68,6 +67,8 @@ extern "C" { void kt_tacocat_receive_process(kt_tacocat_main_t * const main, const f_number_unsigned_t index) { uint16_t * const flag = &main->setting.receive.flags.array[index]; + uint16_t * const retry = &main->setting.receive.retrys.array[index]; + uint32_t * const total = &main->setting.receive.totals.array[index]; f_poll_t * const poll = &main->setting.receive.polls.array[index]; f_socket_t * const socket = &main->setting.receive.sockets.array[index]; f_status_t * const status = &main->setting.receive.statuss.array[index]; @@ -75,62 +76,70 @@ extern "C" { f_string_dynamic_t * const buffer = &main->setting.receive.buffers.array[index]; f_fss_simple_packet_range_t * const packet = &main->setting.receive.packets.array[index]; - //if (poll->revents & f_poll_urgent_e) { // handle out of band, via f_socket_flag_out_of_band_e? - - size_t length = 0; + size_t length_read = 0; // This is a new packet (kt_tacocat_socket_flag_none_e). if (!(*flag)) { + *flag = kt_tacocat_socket_flag_block_begin_e; + *retry = 0; + *total = 0; buffer->used = 0; socket->size_read = kt_tacocat_packet_read_d; } - // @todo this check should also be performed after reading the FSS Packet Header against the FSS Payload length value. - if (main->setting.flag & kt_tacocat_main_flag_max_buffer_e) { - if ((buffer->used + socket->size_read) > main->setting.max_buffer) { - buffer->used = 0; + const size_t size_read = socket->size_read; - if (buffer->size > kt_tacocat_max_maintain_d) { - *status = f_memory_array_resize(kt_tacocat_max_maintain_d, sizeof(f_char_t), (void **) &buffer->string, &buffer->used, &buffer->size); + // @todo move this section into its own function call. + // Load the header of the new packet. + if ((*flag) & kt_tacocat_socket_flag_block_begin_e) { + *status = f_socket_accept(socket); - if (F_status_is_error(*status)) { - kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(f_memory_array_resize), kt_tacocat_receive_s, *name, *status); + // The socket failed to accept and so there is no data socket id to close. + macro_kt_receive_process_handle_error_exit_1(main, f_socket_accept, name, status, flag, 0); - return; - } - } + *status = f_memory_array_increase_by(kt_tacocat_packet_peek_d + 1, sizeof(f_char_t), (void **) &buffer->string, &buffer->used, &buffer->size); + macro_kt_receive_process_handle_error_exit_1(main, f_memory_array_increase_by, name, status, flag, &socket->id_data); - // @todo for all unrecoverable errors, make sure to drop/flush the packet to prevent processing and then reset the status code (otherwise an infinite error loop will occur, which is the current behavior). - *status = F_status_set_error(F_packet_too_large); + socket->size_read = kt_tacocat_packet_peek_d; - kt_tacocat_print_error_on_buffer_too_large(&main->program.error, kt_tacocat_receive_s, *name); + *status = f_socket_read_stream(socket, 0, (void *) (buffer->string + buffer->used), &length_read); - return; - } - } + socket->size_read = size_read; - *status = f_memory_array_increase_by(socket->size_read, sizeof(f_char_t), (void **) &buffer->string, &buffer->used, &buffer->size); + macro_kt_receive_process_handle_error_exit_1(main, f_socket_read_stream, name, status, flag, &socket->id_data); - if (F_status_is_error(*status)) { - kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(f_memory_array_increase_by), kt_tacocat_receive_s, *name, *status); + buffer->used += length_read; - return; - } + // Continue if the packet header is not fully ready (@todo, implement a counter with a max length thaat prevents infinite loop waits, "retry" is intended for this). + if (buffer->used < kt_tacocat_packet_peek_d) { - // This is a new packet (kt_tacocat_socket_flag_none_e). - if (!(*flag)) { - *status = f_socket_accept(socket); + // Peek ahead to see if the client has closed the connection (all the intended data should have been transmitted). + if (length_read) { + memset(main->cache.peek, 0, kt_tacocat_cache_size_peek_d); - if (F_status_is_error(*status)) { - kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(f_socket_accept), kt_tacocat_receive_s, *name, *status); + socket->size_read = kt_tacocat_cache_size_peek_d - 1; + length_read = 0; - return; - } + *status = f_socket_read_stream(socket, f_socket_flag_peek_e | f_socket_flag_wait_not_e, (void *) main->cache.peek, &length_read); - *status = f_socket_read_stream(socket, f_socket_flag_peek_e, (void *) buffer->string, &length); + socket->size_read = size_read; + } - if (F_status_is_error(*status)) { - kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(f_socket_read_stream), kt_tacocat_receive_s, *name, *status); + // Connection is closed when length is 0, which means the packet is too small. + if (!length_read) { + kt_tacocat_print_error_on_packet_too_small(&main->program.error, kt_tacocat_receive_s, *name, kt_tacocat_packet_peek_d, buffer->used); + + buffer->used = 0; + *retry = 0; + *status = F_status_set_error(F_packet_too_small); + *flag -= kt_tacocat_socket_flag_block_begin_e; + + f_file_close_id(&socket->id_data); + + return; + } + + ++(*retry); f_file_close_id(&socket->id_data); @@ -144,18 +153,56 @@ extern "C" { packet->payload.start = 1; packet->payload.stop = 0; + // @todo need to check/handle if all of the parts exists (want F_okay, but check F_partial, F_data_not, and F_valid_not (F_valid_not has error bit set). *status = f_fss_simple_packet_identify(*buffer, packet); + macro_kt_receive_process_handle_error_exit_1(main, f_fss_simple_packet_identify, name, status, flag, &socket->id_data); - if (F_status_is_error(*status)) { - kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(f_fss_simple_packet_identify), kt_tacocat_receive_s, *name, *status); + // @todo this needs to be wrapped in big/little endian checks, but for now just use ntohl. + *total = ntohl(*((uint32_t *) (buffer->string + 1))); + if (*total <= F_fss_simple_packet_block_header_size_d) { + // @todo handle error, perform memory clearing and possibly send try again message to client but for now, just close the connection gracefully. f_file_close_id(&socket->id_data); + *flag -= kt_tacocat_socket_flag_block_begin_e; + return; } + + if (main->setting.flag & kt_tacocat_main_flag_max_buffer_e) { + if (*total > main->setting.max_buffer) { + buffer->used = 0; + + if (buffer->size > kt_tacocat_max_maintain_d) { + *status = f_memory_array_resize(kt_tacocat_max_maintain_d, sizeof(f_char_t), (void **) &buffer->string, &buffer->used, &buffer->size); + + // Report the resize error but do not fail. + if (F_status_is_error(*status)) { + kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(f_memory_array_resize), kt_tacocat_receive_s, *name, *status); + } + } + + // @todo for all unrecoverable errors, make sure to drop/flush the packet to prevent processing and then reset the status code (otherwise an infinite error loop will occur, which is the current behavior). + *status = F_status_set_error(F_packet_too_large); + + kt_tacocat_print_error_on_buffer_too_large(&main->program.error, kt_tacocat_receive_s, *name); // @todo pass total parameter to print requested packet size. + + // @todo send message to client that the packet is too large but for now, just close the connection gracefully. + f_file_close_id(&socket->id_data); + + return; + } + } + + *flag -= kt_tacocat_socket_flag_block_begin_e; + *flag |= kt_tacocat_socket_flag_block_control_e; } - socket->size_read = kt_tacocat_packet_read_d; + *status = f_memory_array_increase_by(socket->size_read, sizeof(f_char_t), (void **) &buffer->string, &buffer->used, &buffer->size); + macro_kt_receive_process_handle_error_exit_2(main, f_memory_array_increase_by, name, status, flag, &socket->id_data); + + *status = f_socket_read_stream(socket, f_socket_flag_wait_not_e, (void *) buffer->string, &length_read); + macro_kt_receive_process_handle_error_exit_2(main, f_socket_read_stream, name, status, flag, &socket->id_data); //kt_tacocat_socket_flag_none_e = 0x0, //kt_tacocat_socket_flag_block_control_e = 0x1, @@ -167,12 +214,13 @@ extern "C" { // For now just close the socket until the appropriate code gets written here. f_file_close_id(&socket->id_data); - // @todo perform this check only when fully finished processing all of the packet parts. + // @todo perform this check only when fully finished processing all of the packet parts (expected *total is reached). if (buffer->size > kt_tacocat_max_maintain_d) { buffer->used = 0; *status = f_memory_array_resize(kt_tacocat_max_maintain_d, sizeof(f_char_t), (void **) &buffer->string, &buffer->used, &buffer->size); + // Report the resize error but do not fail. if (F_status_is_error(*status)) { kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(f_memory_array_resize), kt_tacocat_receive_s, *name, *status); } diff --git a/sources/c/tacocat/main/tacocat.h b/sources/c/tacocat/main/tacocat.h index 8331c78..8bd461e 100644 --- a/sources/c/tacocat/main/tacocat.h +++ b/sources/c/tacocat/main/tacocat.h @@ -35,6 +35,7 @@ #include #include #include +#include #include // FLL-1 includes.