From: Kevin Day Date: Wed, 16 Mar 2022 04:34:00 +0000 (-0500) Subject: Progress: Continue working on control and controller. X-Git-Tag: 0.5.9~76 X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=773804772a8e3756cdc0be6c66ae6e86a7a05354;p=fll Progress: Continue working on control and controller. This focuses on the control end of things. This pulls in several dependencies that are needed to process the packet. --- diff --git a/level_3/control/c/control.c b/level_3/control/c/control.c index dc49685..bc1ae53 100644 --- a/level_3/control/c/control.c +++ b/level_3/control/c/control.c @@ -30,7 +30,7 @@ extern "C" { fll_program_print_help_option(main->output.to, main->context, control_short_settings_s, control_long_settings_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Specify a directory path or a full path to the control settings file."); fll_program_print_help_option(main->output.to, main->context, control_short_socket_s, control_long_socket_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a directory path or a full path to the controller socket file."); - fll_program_print_help_usage(main->output.to, main->context, control_program_name_s, control_command_s); + fll_program_print_help_usage(main->output.to, main->context, control_program_name_s, control_action_s); fl_print_format(" When the %[%r%r%] parameter represents a directory path then the file name is generated from either the", main->output.to.stream, main->context.set.notable, f_console_symbol_long_enable_s, control_long_socket_s, main->context.set.notable); fl_print_format(" %[%r%r%] parameter or from the control settings file.%r%r", main->output.to.stream, main->context.set.notable, f_console_symbol_long_enable_s, control_long_name_s, main->context.set.notable, f_string_eol_s, f_string_eol_s); @@ -191,12 +191,13 @@ extern "C" { control_data_t data = control_data_t_initialize; data.argv = main->parameters.arguments.array; - // Verify commands before attempting to connect to the socket. - if (control_command_identify(main, &data, data.argv[main->parameters.remaining.array[0]]) == F_found) { - status = control_command_verify(main, &data); + data.action = control_action_identify(main, &data, data.argv[main->parameters.remaining.array[0]]); + + if (data.action) { + status = control_action_verify(main, &data); } else { - control_print_error_parameter_command_not(main, data.argv[main->parameters.remaining.array[0]]); + control_print_error_parameter_action_not(main, data.argv[main->parameters.remaining.array[0]]); status = F_status_set_error(F_parameter); } @@ -238,7 +239,9 @@ extern "C" { } if (F_status_is_error_not(status)) { - status = control_packet_receive(main, &data); + control_payload_header_t header = control_payload_header_t_initialize; + + status = control_packet_receive(main, &data, &header); if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_too_large) { @@ -260,7 +263,7 @@ extern "C" { control_data_delete(&data); } else { - control_print_error_parameter_commands_none(main); + control_print_error_parameter_actions_none(main); status = F_status_set_error(F_data_not); } diff --git a/level_3/control/c/control.h b/level_3/control/c/control.h index b82714a..71807da 100644 --- a/level_3/control/c/control.h +++ b/level_3/control/c/control.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -32,8 +33,10 @@ #include #include #include +#include // FLL-1 includes. +#include #include #include #include @@ -44,6 +47,7 @@ #include #include #include +#include // Control includes. #include diff --git a/level_3/control/c/private-common.c b/level_3/control/c/private-common.c index 2e82422..1dffbfb 100644 --- a/level_3/control/c/private-common.c +++ b/level_3/control/c/private-common.c @@ -17,8 +17,9 @@ extern "C" { const f_string_static_t control_path_settings_s = macro_f_string_static_t_initialize(CONTROL_path_settings_s, 0, CONTROL_path_settings_s_length); const f_string_static_t control_action_s = macro_f_string_static_t_initialize(CONTROL_action_s, 0, CONTROL_action_s_length); - const f_string_static_t control_command_s = macro_f_string_static_t_initialize(CONTROL_command_s, 0, CONTROL_command_s_length); + const f_string_static_t control_controller_s = macro_f_string_static_t_initialize(CONTROL_controller_s, 0, CONTROL_controller_s_length); const f_string_static_t control_default_s = macro_f_string_static_t_initialize(CONTROL_default_s, 0, CONTROL_default_s_length); + const f_string_static_t control_error_s = macro_f_string_static_t_initialize(CONTROL_error_s, 0, CONTROL_error_s_length); const f_string_static_t control_length_s = macro_f_string_static_t_initialize(CONTROL_length_s, 0, CONTROL_length_s_length); const f_string_static_t control_name_socket_s = macro_f_string_static_t_initialize(CONTROL_name_socket_s, 0, CONTROL_name_socket_s_length); const f_string_static_t control_path_socket_s = macro_f_string_static_t_initialize(CONTROL_path_socket_s, 0, CONTROL_path_socket_s_length); @@ -27,7 +28,6 @@ extern "C" { const f_string_static_t control_status_s = macro_f_string_static_t_initialize(CONTROL_status_s, 0, CONTROL_status_s_length); const f_string_static_t control_type_s = macro_f_string_static_t_initialize(CONTROL_type_s, 0, CONTROL_type_s_length); - const f_string_static_t control_error_s = macro_f_string_static_t_initialize(CONTROL_error_s, 0, CONTROL_error_s_length); const f_string_static_t control_freeze_s = macro_f_string_static_t_initialize(CONTROL_freeze_s, 0, CONTROL_freeze_s_length); const f_string_static_t control_kill_s = macro_f_string_static_t_initialize(CONTROL_kill_s, 0, CONTROL_kill_s_length); const f_string_static_t control_pause_s = macro_f_string_static_t_initialize(CONTROL_pause_s, 0, CONTROL_pause_s_length); @@ -52,15 +52,10 @@ extern "C" { f_string_ranges_resize(0, &data->cache.packet_objects); f_string_rangess_resize(0, &data->cache.packet_contents); - f_string_ranges_resize(0, &data->cache.payload_objects); - f_string_rangess_resize(0, &data->cache.payload_contents); + f_string_ranges_resize(0, &data->cache.header_objects); + f_string_rangess_resize(0, &data->cache.header_contents); f_array_lengths_resize(0, &data->cache.delimits); - - f_string_ranges_resize(0, &data->cache.range_actions); - f_string_ranges_resize(0, &data->cache.range_statuss); - - f_uint8s_resize(0, &data->cache.types); } #endif // _di_control_data_delete_ diff --git a/level_3/control/c/private-common.h b/level_3/control/c/private-common.h index 36fd0ea..b8214a2 100644 --- a/level_3/control/c/private-common.h +++ b/level_3/control/c/private-common.h @@ -128,8 +128,9 @@ extern "C" { #endif // defined(_override_control_path_settings_) && defined(_override_control_path_settings_length_) #define CONTROL_action_s "action" - #define CONTROL_command_s "command" + #define CONTROL_controller_s "controller" #define CONTROL_default_s "default" + #define CONTROL_error_s "error" #define CONTROL_length_s "length" #define CONTROL_name_socket_s "name_socket" #define CONTROL_path_socket_s "path_socket" @@ -138,7 +139,6 @@ extern "C" { #define CONTROL_status_s "status" #define CONTROL_type_s "type" - #define CONTROL_error_s "error" #define CONTROL_freeze_s "freeze" #define CONTROL_kill_s "kill" #define CONTROL_pause_s "pause" @@ -152,18 +152,18 @@ extern "C" { #define CONTROL_stop_s "stop" #define CONTROL_thaw_s "thaw" - #define CONTROL_command_s_length 7 + #define CONTROL_action_s_length 6 + #define CONTROL_controller_s_length 10 #define CONTROL_default_s_length 7 + #define CONTROL_error_s_length 5 + #define CONTROL_length_s_length 6 #define CONTROL_name_socket_s_length 11 #define CONTROL_path_socket_s_length 11 #define CONTROL_path_socket_prefix_s_length 18 #define CONTROL_path_socket_suffix_s_length 18 - #define CONTROL_type_s_length 4 #define CONTROL_status_s_length 6 - #define CONTROL_length_s_length 6 - #define CONTROL_action_s_length 6 + #define CONTROL_type_s_length 4 - #define CONTROL_error_s_length 5 #define CONTROL_freeze_s_length 6 #define CONTROL_kill_s_length 4 #define CONTROL_pause_s_length 5 @@ -180,8 +180,9 @@ extern "C" { extern const f_string_static_t control_path_settings_s; extern const f_string_static_t control_action_s; - extern const f_string_static_t control_command_s; + extern const f_string_static_t control_controller_s; extern const f_string_static_t control_default_s; + extern const f_string_static_t control_error_s; extern const f_string_static_t control_length_s; extern const f_string_static_t control_name_socket_s; extern const f_string_static_t control_path_socket_s; @@ -190,7 +191,6 @@ extern "C" { extern const f_string_static_t control_status_s; extern const f_string_static_t control_type_s; - extern const f_string_static_t control_error_s; extern const f_string_static_t control_freeze_s; extern const f_string_static_t control_kill_s; extern const f_string_static_t control_pause_s; @@ -206,7 +206,7 @@ extern "C" { #endif // _di_control_strings_s_ /** - * Codes representing supported commands. + * Codes representing supported actions. * * freeze: Perform the freeze controller operation. * kill: Perform the kill controller operation. @@ -221,22 +221,22 @@ extern "C" { * stop: Perform the stop controller operation. * thaw: Perform the thaw controller operation. */ -#ifndef _di_control_command_types_ +#ifndef _di_control_action_types_ enum { - control_command_type_freeze_e = 1, - control_command_type_kill_e, - control_command_type_pause_e, - control_command_type_reboot_e, - control_command_type_reload_e, - control_command_type_rerun_e, - control_command_type_restart_e, - control_command_type_resume_e, - control_command_type_shutdown_e, - control_command_type_start_e, - control_command_type_stop_e, - control_command_type_thaw_e, + control_action_type_freeze_e = 1, + control_action_type_kill_e, + control_action_type_pause_e, + control_action_type_reboot_e, + control_action_type_reload_e, + control_action_type_rerun_e, + control_action_type_restart_e, + control_action_type_resume_e, + control_action_type_shutdown_e, + control_action_type_start_e, + control_action_type_stop_e, + control_action_type_thaw_e, }; -#endif // _di_control_command_types_ +#endif // _di_control_action_types_ /** * The control cache. @@ -248,8 +248,8 @@ extern "C" { * packet_objects: The FSS Objects for a packet. * packet_contents: The FSS Contents for a packet. * - * payload_objects: The FSS Objects for a payload. - * payload_contents: The FSS Contents for a payload. + * header_objects: The FSS Objects for a packet payload header. + * header_contents: The FSS Contents for a packet payload header. * * delimits: The delimits cache. */ @@ -262,15 +262,10 @@ extern "C" { f_fss_objects_t packet_objects; f_fss_contents_t packet_contents; - f_fss_objects_t payload_objects; - f_fss_contents_t payload_contents; + f_fss_objects_t header_objects; + f_fss_contents_t header_contents; f_fss_delimits_t delimits; - - f_string_ranges_t range_actions; - f_string_ranges_t range_statuss; - - f_uint8s_t types; } control_cache_t; #define control_cache_initialize \ @@ -283,23 +278,20 @@ extern "C" { f_fss_objects_t_initialize, \ f_fss_contents_t_initialize, \ f_fss_delimits_t_initialize, \ - f_string_ranges_t_initialize, \ - f_string_ranges_t_initialize, \ - f_uint8s_t_initialize, \ } #endif // _di_control_cache_t_ /** * The control data. * - * argv: The argument structure in the progam data parameters for simplifying syntax. - * command: The command type code. - * cache: A cache. - * socket: A socket used to connect to the controller. + * argv: The argument structure in the progam data parameters for simplifying syntax. + * action: The action type code. + * cache: A cache. + * socket: A socket used to connect to the controller. */ #ifndef _di_control_data_t_ typedef struct { - uint8_t command; + uint8_t action; control_cache_t cache; @@ -319,6 +311,46 @@ extern "C" { #endif // _di_control_data_t_ /** + * Supported payload types. + * + * error: The payload is an error payload. + * controller: The payload is a controller payload. + */ +#ifndef _di_control_payload_types_ + enum { + control_payload_type_error_e = 1, + control_payload_type_controller_e, + }; +#endif // _di_control_payload_types_ + +/** + * The packet payload header data. + * + * The FSS-000E (Payload) supports multiple objects, but the Control packet does not support this, yet. + * + * action: The action type code, for any valid action (see: control_action_types enumeration). + * type: The packet type represented by the payload packet. + * status: The status code represented by the payload packet. + * length: The length of the payload content within the payload packet. + */ +#ifndef _di_control_payload_header_t_ + typedef struct { + uint8_t action; + uint8_t type; + f_status_t status; + uint16_t length; + } control_payload_header_t; + + #define control_payload_header_t_initialize \ + { \ + 0, \ + 0, \ + f_status_t_initialize, \ + f_array_length_t_initialize, \ + } +#endif // _di_control_payload_header_t_ + +/** * Deallocate the control data. * * @param data diff --git a/level_3/control/c/private-control.c b/level_3/control/c/private-control.c index 4b8016e..533265f 100644 --- a/level_3/control/c/private-control.c +++ b/level_3/control/c/private-control.c @@ -7,116 +7,92 @@ extern "C" { #endif -#ifndef _di_control_command_identify_ - f_status_t control_command_identify(fll_program_data_t * const main, control_data_t * const data, const f_string_static_t command) { +#ifndef _di_control_action_identify_ + uint8_t control_action_identify(fll_program_data_t * const main, control_data_t * const data, const f_string_static_t action) { - if (fl_string_dynamic_compare(command, control_freeze_s) == F_equal_to) { - data->command = control_command_type_freeze_e; - - return F_found; + if (fl_string_dynamic_compare(action, control_freeze_s) == F_equal_to) { + return control_action_type_freeze_e; } - if (fl_string_dynamic_compare(command, control_kill_s) == F_equal_to) { - data->command = control_command_type_kill_e; - - return F_found; + if (fl_string_dynamic_compare(action, control_kill_s) == F_equal_to) { + return control_action_type_kill_e; } - if (fl_string_dynamic_compare(command, control_pause_s) == F_equal_to) { - data->command = control_command_type_pause_e; - - return F_found; + if (fl_string_dynamic_compare(action, control_pause_s) == F_equal_to) { + return control_action_type_pause_e; } - if (fl_string_dynamic_compare(command, control_reboot_s) == F_equal_to) { - data->command = control_command_type_reboot_e; - - return F_found; + if (fl_string_dynamic_compare(action, control_reboot_s) == F_equal_to) { + return control_action_type_reboot_e; } - if (fl_string_dynamic_compare(command, control_reload_s) == F_equal_to) { - data->command = control_command_type_reload_e; - - return F_found; + if (fl_string_dynamic_compare(action, control_reload_s) == F_equal_to) { + return control_action_type_reload_e; } - if (fl_string_dynamic_compare(command, control_rerun_s) == F_equal_to) { - data->command = control_command_type_rerun_e; - - return F_found; + if (fl_string_dynamic_compare(action, control_rerun_s) == F_equal_to) { + return control_action_type_rerun_e; } - if (fl_string_dynamic_compare(command, control_restart_s) == F_equal_to) { - data->command = control_command_type_restart_e; - - return F_found; + if (fl_string_dynamic_compare(action, control_restart_s) == F_equal_to) { + return control_action_type_restart_e; } - if (fl_string_dynamic_compare(command, control_resume_s) == F_equal_to) { - data->command = control_command_type_resume_e; - - return F_found; + if (fl_string_dynamic_compare(action, control_resume_s) == F_equal_to) { + return control_action_type_resume_e; } - if (fl_string_dynamic_compare(command, control_shutdown_s) == F_equal_to) { - data->command = control_command_type_shutdown_e; - - return F_found; + if (fl_string_dynamic_compare(action, control_shutdown_s) == F_equal_to) { + return control_action_type_shutdown_e; } - if (fl_string_dynamic_compare(command, control_start_s) == F_equal_to) { - data->command = control_command_type_start_e; - - return F_found; + if (fl_string_dynamic_compare(action, control_start_s) == F_equal_to) { + return control_action_type_start_e; } - if (fl_string_dynamic_compare(command, control_stop_s) == F_equal_to) { - data->command = control_command_type_stop_e; - - return F_found; + if (fl_string_dynamic_compare(action, control_stop_s) == F_equal_to) { + return control_action_type_stop_e; } - if (fl_string_dynamic_compare(command, control_thaw_s) == F_equal_to) { - data->command = control_command_type_thaw_e; - - return F_found; + if (fl_string_dynamic_compare(action, control_thaw_s) == F_equal_to) { + return control_action_type_thaw_e; } - return F_found_not; + return 0; } -#endif // _di_control_command_identify_ - -#ifndef _di_control_command_verify_ - f_status_t control_command_verify(fll_program_data_t * const main, control_data_t * const data) { - - switch (data->command) { - case control_command_type_freeze_e: - case control_command_type_kill_e: - case control_command_type_pause_e: - case control_command_type_reload_e: - case control_command_type_rerun_e: - case control_command_type_restart_e: - case control_command_type_resume_e: - case control_command_type_start_e: - case control_command_type_stop_e: - case control_command_type_thaw_e: +#endif // _di_control_action_identify_ + +#ifndef _di_control_action_verify_ + f_status_t control_action_verify(fll_program_data_t * const main, control_data_t * const data) { + + switch (data->action) { + case control_action_type_freeze_e: + case control_action_type_kill_e: + case control_action_type_pause_e: + case control_action_type_reload_e: + case control_action_type_rerun_e: + case control_action_type_restart_e: + case control_action_type_resume_e: + case control_action_type_start_e: + case control_action_type_stop_e: + case control_action_type_thaw_e: if (main->parameters.remaining.used < 2) { - control_print_error_parameter_command_rule_not(main, data->argv[main->parameters.remaining.array[0]]); + control_print_error_parameter_action_rule_not(main, data->argv[main->parameters.remaining.array[0]]); return F_status_set_error(F_parameter); } else if (main->parameters.remaining.used > 3) { - control_print_error_parameter_command_rule_too_many(main, data->argv[main->parameters.remaining.array[0]]); + control_print_error_parameter_action_rule_too_many(main, data->argv[main->parameters.remaining.array[0]]); return F_status_set_error(F_parameter); } if (!data->argv[main->parameters.remaining.array[1]].used) { if (main->parameters.remaining.used == 2) { - control_print_error_parameter_command_rule_empty(main, data->argv[main->parameters.remaining.array[0]]); + control_print_error_parameter_action_rule_empty(main, data->argv[main->parameters.remaining.array[0]]); } else { - control_print_error_parameter_command_rule_directory_empty(main, data->argv[main->parameters.remaining.array[0]]); + control_print_error_parameter_action_rule_directory_empty(main, data->argv[main->parameters.remaining.array[0]]); } return F_status_set_error(F_parameter); @@ -124,7 +100,7 @@ extern "C" { if (main->parameters.remaining.used == 3) { if (!data->argv[main->parameters.remaining.array[2]].used) { - control_print_error_parameter_command_rule_basename_empty(main, data->argv[main->parameters.remaining.array[0]]); + control_print_error_parameter_action_rule_basename_empty(main, data->argv[main->parameters.remaining.array[0]]); return F_status_set_error(F_parameter); } @@ -133,18 +109,18 @@ extern "C" { return F_none; } - // @todo the reboot and shutdown need to support date and time commands: "now", "in (a time)", and "at (a time)". - if (data->command == control_command_type_reboot_e) { - // @todo (also needs to support kexec calls or kexec needs its own command, which will likely be in the controller program.) + // @todo the reboot and shutdown need to support date and time actions: "now", "in (a time)", and "at (a time)". + if (data->action == control_action_type_reboot_e) { + // @todo (also needs to support kexec calls or kexec needs its own action, which will likely be in the controller program.) } - if (data->command == control_command_type_shutdown_e) { + if (data->action == control_action_type_shutdown_e) { // @todo } return F_none; } -#endif // _di_control_command_verify_ +#endif // _di_control_action_verify_ #ifndef _di_control_packet_build_ f_status_t control_packet_build(fll_program_data_t * const main, control_data_t * const data) { @@ -256,23 +232,28 @@ extern "C" { #endif // _di_control_packet_build_ #ifndef _di_control_packet_receive_ - f_status_t control_packet_receive(fll_program_data_t * const main, control_data_t * const data) { + f_status_t control_packet_receive(fll_program_data_t * const main, control_data_t * const data, control_payload_header_t * const header) { data->cache.large.used = 0; data->cache.small.used = 0; data->cache.packet_objects.used = 0; data->cache.packet_contents.used = 0; - data->cache.payload_objects.used = 0; - data->cache.payload_contents.used = 0; + data->cache.header_objects.used = 0; + data->cache.header_contents.used = 0; data->cache.delimits.used = 0; - data->cache.range_actions.used = 0; - data->cache.range_statuss.used = 0; - data->cache.types.used = 0; + + header->action = 0; + header->type = 0; + header->status = F_none; + header->length = 0; f_status_t status = F_none; - f_array_length_t length = 5; + f_array_length_t i = 0; + f_string_range_t range_header = f_string_range_t_initialize; + f_string_range_t range_payload = f_string_range_t_initialize; { + f_array_length_t length = 5; uint8_t head[length]; memset(head, 0, sizeof(uint8_t) * length); @@ -341,43 +322,174 @@ extern "C" { data->cache.delimits.used = 0; - f_string_range_t *range_header_object = 0; - f_string_ranges_t *range_header_content = 0; - f_string_range_t *range_payload_object = 0; - f_string_ranges_t *range_payload_content = 0; + { + f_string_ranges_t *content_header = 0; + f_string_ranges_t *content_payload = 0; + + for (; i < data->cache.packet_objects.used; ++i) { - for (f_array_length_t i = 0; i < data->cache.packet_objects.used; ++i) { + if (fl_string_dynamic_partial_compare_string(f_fss_string_header_s.string, data->cache.large, f_fss_string_header_s.used, data->cache.packet_objects.array[i]) == F_equal_to) { - if (fl_string_dynamic_partial_compare_string(f_fss_string_header_s.string, data->cache.large, f_fss_string_header_s.used, data->cache.packet_objects.array[i]) == F_equal_to) { + // The FSS-000E (Payload) standard does not prohibit multiple "header", but such cases are not supported by the controller and the control programs. + if (content_header) { + return F_status_set_error(F_packet_not); + } - // The FSS-000E (Payload) standard does not prohibit multiple "header", but such cases are not supported by the controller and the control programs. - if (range_header_object) { - return F_status_set_error(F_packet_not); + content_header = &data->cache.packet_contents.array[i]; } + else if (fl_string_dynamic_partial_compare_string(f_fss_string_payload_s.string, data->cache.large, f_fss_string_payload_s.used, data->cache.packet_objects.array[i]) == F_equal_to) { - range_header_object = &data->cache.packet_objects.array[i]; - range_header_content = &data->cache.packet_contents.array[i]; - } - else if (fl_string_dynamic_partial_compare_string(f_fss_string_payload_s.string, data->cache.large, f_fss_string_payload_s.used, data->cache.packet_objects.array[i]) == F_equal_to) { + // Only a single "payload" is supported by the FSS-000E (Payload) standard. + if (content_payload) { + return F_status_set_error(F_packet_not); + } - // Only a single "payload" is supported by the FSS-000E (Payload) standard. - if (range_payload_object) { - return F_status_set_error(F_packet_not); + content_payload = &data->cache.packet_contents.array[i]; } + } // for - range_payload_object = &data->cache.packet_objects.array[i]; - range_payload_content = &data->cache.packet_contents.array[i]; + if (!content_header || !content_payload) { + return F_status_set_error(F_packet_not); } - } // for - if (!range_header_object || !range_payload_object) { - return F_status_set_error(F_packet_not); + range_header = content_header->array[0]; + range_payload = content_payload->array[0]; } - // @todo load the "action"s, "length", "status"s, "type"s, and finally the "payload" (if lenth is > 0). + { + // 0x1 = found action, 0x2 = found length, 0x4 = found status, 0x8 = found_type. + uint8_t found = 0; + f_number_unsigned_t number = 0; + f_string_range_t range = range_header; + + status = fll_fss_basic_list_read(data->cache.large, state, &range, &data->cache.header_objects, &data->cache.header_contents, &data->cache.delimits, 0, 0); + if (F_status_is_error(status)) return F_status_set_error(status); + + status = fl_fss_apply_delimit(data->cache.delimits, &data->cache.large); + if (F_status_is_error(status)) return status; + + if (!data->cache.header_contents.used) { + // @todo if debug print the reason for the failure. + return F_status_set_error(F_header); + } + + // @todo walk through each range in header_objects, match the first "header" object, get the range from header_contents.array[0], reset the header_objects and header_contents and then pass the retrieved range to the fll_fss_extended_read() function below. + + //status = fll_fss_extended_read(data->cache.large, state, &range, &data->cache.header_objects, &data->cache.header_contents, &data->cache.delimits, 0, 0); + if (F_status_is_error(status)) return F_status_set_error(status); + + for (i = 0; i < data->cache.header_objects.used; ++i) { + + if (fl_string_dynamic_partial_compare_string(control_action_s.string, data->cache.large, control_action_s.used, data->cache.header_objects.array[i]) == F_equal_to) { + if (!(found & 0x1)) { + const f_array_length_t action_length = (data->cache.header_contents.array[i].array[0].stop - data->cache.header_contents.array[i].array[0].start) + 1; + char action_string[action_length + 1]; + const f_string_static_t action = macro_f_string_static_t_initialize(action_string, 0, action_length); + + memcpy(action_string, data->cache.large.string + data->cache.header_contents.array[i].array[0].start, action_length); + action_string[action_length] = 0; + + found |= 0x1; + + control_print_debug_packet_header_object_and_content(main, control_action_s, data->cache.large, data->cache.header_contents.array[i].array[0]); + + header->action = control_action_identify(main, data, action); + + if (!header->action) { + // @todo if debug print the reason for the failure. + return F_status_set_error(F_header); + } + } + else { + control_print_warning_packet_header_duplicate_object(main, control_action_s); + } + } + else if (fl_string_dynamic_partial_compare_string(control_length_s.string, data->cache.large, control_length_s.used, data->cache.header_objects.array[i]) == F_equal_to) { + if (!(found & 0x2)) { + found |= 0x2; + number = 0; + + control_print_debug_packet_header_object_and_content(main, control_length_s, data->cache.large, data->cache.header_contents.array[i].array[0]); + + // First attempt to get status as a number. + status = fl_conversion_dynamic_partial_to_number_unsigned(data->cache.large, data->cache.header_contents.array[i].array[0], &number); + + if (F_status_is_error(status)) { + // @todo if debug print the reason for the failure. + return F_status_set_error(F_status); + } + + if (number > F_status_size_max_with_bits_d) { + // @todo if debug print the reason for the failure. + return F_status_set_error(F_status); + } + + header->length = (uint16_t) number; + } + else { + control_print_warning_packet_header_duplicate_object(main, control_length_s); + } + } + else if (fl_string_dynamic_partial_compare_string(control_status_s.string, data->cache.large, control_status_s.used, data->cache.header_objects.array[i]) == F_equal_to) { + if (!(found & 0x4)) { + found |= 0x4; + number = 0; + + control_print_debug_packet_header_object_and_content(main, control_status_s, data->cache.large, data->cache.header_contents.array[i].array[0]); + + // First attempt to get status as a number. + status = fl_conversion_dynamic_partial_to_number_unsigned(data->cache.large, data->cache.header_contents.array[i].array[0], &number); + + if (F_status_set_fine(status) == F_number) { + const f_array_length_t name_length = (data->cache.header_contents.array[i].array[0].stop - data->cache.header_contents.array[i].array[0].start) + 1; + char name_string[name_length + 1]; + const f_string_static_t name = macro_f_string_static_t_initialize(name_string, 0, name_length); + + memcpy(name_string, data->cache.large.string + data->cache.header_contents.array[i].array[0].start, name_length); + name_string[name_length] = 0; + + status = fll_status_string_from(name, &header->status); + + if (F_status_is_error(status)) { + // @todo if debug print the reason for the failure. + return status; + } + } + else if (F_status_is_error(status)) { + // @todo if debug print the reason for the failure. + return F_status_set_error(F_status); + } + } + else { + control_print_warning_packet_header_duplicate_object(main, control_length_s); + } + } + else if (fl_string_dynamic_partial_compare_string(control_type_s.string, data->cache.large, control_type_s.used, data->cache.header_objects.array[i]) == F_equal_to) { + if (!(found & 0x8)) { + found |= 0x8; + + control_print_debug_packet_header_object_and_content(main, control_type_s, data->cache.large, data->cache.header_contents.array[i].array[0]); + + if (fl_string_dynamic_partial_compare_string(control_controller_s.string, data->cache.large, control_controller_s.used, data->cache.header_contents.array[i].array[0]) == F_equal_to) { + header->type = control_payload_type_controller_e; + } + else if (fl_string_dynamic_partial_compare_string(control_error_s.string, data->cache.large, control_error_s.used, data->cache.header_contents.array[i].array[0]) == F_equal_to) { + header->type = control_payload_type_error_e; + } + else { + // @todo if debug print the reason for the failure. + return F_status_set_error(F_header); + } + } + else { + control_print_warning_packet_header_duplicate_object(main, control_type_s); + } + } + } + } - //status = fll_fss_extended_read(data->cache.payload, state, range_payload_content, &data->cache.payload_objects, &data->cache.payload_contents, &data->cache.delimits, 0, 0); - //if (F_status_is_error(status)) return status; + // @todo based on header->type, handle the data. if type is control_payload_type_error_e, then check the header->length and conditionally get the message from the payload content. + // @todo this handling may likely be moved outside of this function. } // @todo diff --git a/level_3/control/c/private-control.h b/level_3/control/c/private-control.h index a628109..89b7bf3 100644 --- a/level_3/control/c/private-control.h +++ b/level_3/control/c/private-control.h @@ -14,34 +14,34 @@ extern "C" { /** - * Identify the command code the given name represents. + * Identify the action code the given name represents. * * @param main * The main program data. * @param data * The control data. - * @param command - * The parameter representing a command. + * @param action + * The parameter representing a action. * * @return - * F_found on success. - * F_found_not if name is unknown. + * action type code on success. + * 0 if name is unknown. */ -#ifndef _di_control_command_identify_ - extern f_status_t control_command_identify(fll_program_data_t * const main, control_data_t * const data, const f_string_static_t command) F_attribute_visibility_internal_d; -#endif // _di_control_command_identify_ +#ifndef _di_control_action_identify_ + extern uint8_t control_action_identify(fll_program_data_t * const main, control_data_t * const data, const f_string_static_t action) F_attribute_visibility_internal_d; +#endif // _di_control_action_identify_ /** - * Verify that the additional parameters are reasonably correct for the identified command. + * Verify that the additional parameters are reasonably correct for the identified action. * * @param main * The main program data. * @param data * The control data. */ -#ifndef _di_control_command_verify_ - extern f_status_t control_command_verify(fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d; -#endif // _di_control_command_verify_ +#ifndef _di_control_action_verify_ + extern f_status_t control_action_verify(fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d; +#endif // _di_control_action_verify_ /** * Build the payload, storing it in the large cache. @@ -71,14 +71,19 @@ extern "C" { /** * Receive the response from the remote socket, storing it in the large cache. * + * @todo consider returning F_header (with error bit) fo most header processing errors rather than individual status codes. + * * @param main * The main program data. * @param data * The control data. + * @param header + * The control payload packet header data. * * @return * F_none on success. * + * F_header (with error bit) If there is a problem processing the packet header. * F_packet_not (with error bit) If the received packet is not a valid packet or not a supported packet structure. * F_too_large (with error bit) If the received packet specifies a size that is too large or the actual size is larger than the specified size. * F_too_small (with error bit) If the received packet actual size is smaller than the specified size. @@ -100,7 +105,7 @@ extern "C" { * @see fll_fss_extended_read() */ #ifndef _di_control_packet_receive_ - extern f_status_t control_packet_receive(fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d; + extern f_status_t control_packet_receive(fll_program_data_t * const main, control_data_t * const data, control_payload_header_t * const header) F_attribute_visibility_internal_d; #endif // _di_control_packet_receive_ /** diff --git a/level_3/control/c/private-print.c b/level_3/control/c/private-print.c index e5fa830..e218a7f 100644 --- a/level_3/control/c/private-print.c +++ b/level_3/control/c/private-print.c @@ -6,104 +6,118 @@ extern "C" { #endif -#ifndef _di_control_print_error_parameter_commands_none_ - void control_print_error_parameter_commands_none(fll_program_data_t * const main) { +#ifndef _di_control_print_debug_packet_header_object_and_content_ + void control_print_debug_packet_header_object_and_content(fll_program_data_t * const main, const f_string_static_t object, const f_string_static_t content, const f_string_range_t range_content) { + + if (main->output.verbosity == f_console_verbosity_debug_e) return; + + flockfile(main->error.to.stream); + + fl_print_format("%rPacket header Object '%[%Q%]", main->output.to.stream, f_string_eol_s, main->context.set.notable, object, main->context.set.notable); + fl_print_format("' has value '%[%/Q%]'.%r", main->output.to.stream, main->context.set.notable, content, range_content, main->context.set.notable, f_string_eol_s); + + funlockfile(main->error.to.stream); + } +#endif // _di_control_print_debug_packet_header_object_and_content_ + +#ifndef _di_control_print_error_parameter_actions_none_ + void control_print_error_parameter_actions_none(fll_program_data_t * const main) { if (main->error.verbosity == f_console_verbosity_quiet_e) return; - fll_print_format("%r%[%QNo commands provided.%]%r", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error, f_string_eol_s); + fll_print_format("%r%[%QNo actions provided.%]%r", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error, f_string_eol_s); } -#endif // _di_control_print_error_parameter_commands_none_ +#endif // _di_control_print_error_parameter_actions_none_ -#ifndef _di_control_print_error_parameter_command_not_ - void control_print_error_parameter_command_not(fll_program_data_t * const main, const f_string_static_t command) { +#ifndef _di_control_print_error_parameter_action_not_ + void control_print_error_parameter_action_not(fll_program_data_t * const main, const f_string_static_t action) { if (main->error.verbosity == f_console_verbosity_quiet_e) return; flockfile(main->error.to.stream); fl_print_format("%r%[%QThe parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, command, main->context.set.notable); - fl_print_format("%[' is not a known controller command.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, action, main->context.set.notable); + fl_print_format("%[' is not a known controller action.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); funlockfile(main->error.to.stream); } -#endif // _di_control_print_error_parameter_command_not_ +#endif // _di_control_print_error_parameter_action_not_ -#ifndef _di_control_print_error_parameter_command_rule_basename_empty_ - void control_print_error_parameter_command_rule_basename_empty(fll_program_data_t * const main, const f_string_static_t command) { +#ifndef _di_control_print_error_parameter_action_rule_basename_empty_ + void control_print_error_parameter_action_rule_basename_empty(fll_program_data_t * const main, const f_string_static_t action) { if (main->error.verbosity == f_console_verbosity_quiet_e) return; flockfile(main->error.to.stream); - fl_print_format("%r%[%QThe command parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, command, main->context.set.notable); + fl_print_format("%r%[%QThe action parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); + fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, action, main->context.set.notable); fl_print_format("%[' a rule base name cannot be an empty string.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); funlockfile(main->error.to.stream); } -#endif // _di_control_print_error_parameter_command_rule_basename_empty_ +#endif // _di_control_print_error_parameter_action_rule_basename_empty_ -#ifndef _di_control_print_error_parameter_command_rule_directory_empty_ - void control_print_error_parameter_command_rule_directory_empty(fll_program_data_t * const main, const f_string_static_t command) { +#ifndef _di_control_print_error_parameter_action_rule_directory_empty_ + void control_print_error_parameter_action_rule_directory_empty(fll_program_data_t * const main, const f_string_static_t action) { if (main->error.verbosity == f_console_verbosity_quiet_e) return; flockfile(main->error.to.stream); - fl_print_format("%r%[%QThe command parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, command, main->context.set.notable); + fl_print_format("%r%[%QThe action parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); + fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, action, main->context.set.notable); fl_print_format("%[' a rule directory path cannot be an empty string.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); funlockfile(main->error.to.stream); } -#endif // _di_control_print_error_parameter_command_rule_directory_empty_ +#endif // _di_control_print_error_parameter_action_rule_directory_empty_ -#ifndef _di_control_print_error_parameter_command_rule_empty_ - void control_print_error_parameter_command_rule_empty(fll_program_data_t * const main, const f_string_static_t command) { +#ifndef _di_control_print_error_parameter_action_rule_empty_ + void control_print_error_parameter_action_rule_empty(fll_program_data_t * const main, const f_string_static_t action) { if (main->error.verbosity == f_console_verbosity_quiet_e) return; flockfile(main->error.to.stream); - fl_print_format("%r%[%QThe command parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, command, main->context.set.notable); + fl_print_format("%r%[%QThe action parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); + fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, action, main->context.set.notable); fl_print_format("%[' a rule name cannot be an empty string.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); funlockfile(main->error.to.stream); } -#endif // _di_control_print_error_parameter_command_rule_empty_ +#endif // _di_control_print_error_parameter_action_rule_empty_ -#ifndef _di_control_print_error_parameter_command_rule_not_ - void control_print_error_parameter_command_rule_not(fll_program_data_t * const main, const f_string_static_t command) { +#ifndef _di_control_print_error_parameter_action_rule_not_ + void control_print_error_parameter_action_rule_not(fll_program_data_t * const main, const f_string_static_t action) { if (main->error.verbosity == f_console_verbosity_quiet_e) return; flockfile(main->error.to.stream); - fl_print_format("%r%[%QThe command parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, command, main->context.set.notable); + fl_print_format("%r%[%QThe action parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); + fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, action, main->context.set.notable); fl_print_format("%[' requires either a full rule name or a rule directory path along with the rule base name.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); funlockfile(main->error.to.stream); } -#endif // _di_control_print_error_parameter_command_rule_not_ +#endif // _di_control_print_error_parameter_action_rule_not_ -#ifndef _di_control_print_error_parameter_command_rule_too_many_ - void control_print_error_parameter_command_rule_too_many(fll_program_data_t * const main, const f_string_static_t command) { +#ifndef _di_control_print_error_parameter_action_rule_too_many_ + void control_print_error_parameter_action_rule_too_many(fll_program_data_t * const main, const f_string_static_t action) { if (main->error.verbosity == f_console_verbosity_quiet_e) return; flockfile(main->error.to.stream); - fl_print_format("%r%[%QThe command parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); - fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, command, main->context.set.notable); + fl_print_format("%r%[%QThe action parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error); + fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, action, main->context.set.notable); fl_print_format("%[' has too many arguments.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); funlockfile(main->error.to.stream); } -#endif // _di_control_print_error_parameter_command_rule_too_many_ +#endif // _di_control_print_error_parameter_action_rule_too_many_ #ifndef _di_control_print_error_parameter_value_empty_ void control_print_error_parameter_value_empty(fll_program_data_t * const main, const f_string_static_t parameter) { @@ -225,6 +239,21 @@ extern "C" { } #endif // _di_control_print_signal_received_ +#ifndef _di_control_print_warning_packet_header_duplicate_object_ + void control_print_warning_packet_header_duplicate_object(fll_program_data_t * const main, const f_string_static_t response_header) { + + if (main->warning.verbosity == f_console_verbosity_debug_e) return; + + flockfile(main->warning.to.stream); + + fl_print_format("%r%[%QThe received response header '%]", main->warning.to.stream, f_string_eol_s, main->context.set.warning, main->warning.prefix, main->context.set.warning); + fl_print_format("%[%Q%]", main->warning.to.stream, main->context.set.notable, response_header, main->context.set.notable); + fl_print_format("%[' is repeated.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s); + + funlockfile(main->warning.to.stream); + } +#endif // _di_control_print_warning_packet_header_duplicate_object_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/control/c/private-print.h b/level_3/control/c/private-print.h index 1d98b8f..78396b8 100644 --- a/level_3/control/c/private-print.h +++ b/level_3/control/c/private-print.h @@ -13,86 +13,102 @@ extern "C" { #endif /** - * Print an error message about no commands being provided. + * Print a message displaying the object and content for some packet header. * * @param main * The main program data. + * @param object + * The object string. + * @param content + * The content string. + * @param range_content + * The range representing the content where the content is found within the content string. */ -#ifndef _di_control_print_error_parameter_commands_none_ - extern void control_print_error_parameter_commands_none(fll_program_data_t * const main) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_parameter_commands_none_ +#ifndef _di_control_print_debug_packet_header_object_and_content_ + extern void control_print_debug_packet_header_object_and_content(fll_program_data_t * const main, const f_string_static_t object, const f_string_static_t content, const f_string_range_t range_content) F_attribute_visibility_internal_d; +#endif // _di_control_print_debug_packet_header_object_and_content_ /** - * Print an error message about the given parameter not matching the known set of controller commands. + * Print an error message about no actions being provided. * * @param main * The main program data. - * @param command - * The parameter representing a command. */ -#ifndef _di_control_print_error_parameter_command_not_ - extern void control_print_error_parameter_command_not(fll_program_data_t * const main, const f_string_static_t command) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_parameter_command_not_ +#ifndef _di_control_print_error_parameter_actions_none_ + extern void control_print_error_parameter_actions_none(fll_program_data_t * const main) F_attribute_visibility_internal_d; +#endif // _di_control_print_error_parameter_actions_none_ /** - * Print an error message about the given parameter being a rule command having an empty rule basename. + * Print an error message about the given parameter not matching the known set of controller actions. * * @param main * The main program data. - * @param command - * The parameter representing a command. + * @param action + * The parameter representing a action. */ -#ifndef _di_control_print_error_parameter_command_rule_basename_empty_ - extern void control_print_error_parameter_command_rule_basename_empty(fll_program_data_t * const main, const f_string_static_t command) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_parameter_command_rule_basename_empty_ +#ifndef _di_control_print_error_parameter_action_not_ + extern void control_print_error_parameter_action_not(fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d; +#endif // _di_control_print_error_parameter_action_not_ /** - * Print an error message about the given parameter being a rule command having an empty rule directory path. + * Print an error message about the given parameter being a rule action having an empty rule basename. * * @param main * The main program data. - * @param command - * The parameter representing a command. + * @param action + * The parameter representing a action. */ -#ifndef _di_control_print_error_parameter_command_rule_directory_empty_ - extern void control_print_error_parameter_command_rule_directory_empty(fll_program_data_t * const main, const f_string_static_t command) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_parameter_command_rule_directory_empty_ +#ifndef _di_control_print_error_parameter_action_rule_basename_empty_ + extern void control_print_error_parameter_action_rule_basename_empty(fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d; +#endif // _di_control_print_error_parameter_action_rule_basename_empty_ /** - * Print an error message about the given parameter being a rule command having an empty rule name. + * Print an error message about the given parameter being a rule action having an empty rule directory path. * * @param main * The main program data. - * @param command - * The parameter representing a command. + * @param action + * The parameter representing a action. */ -#ifndef _di_control_print_error_parameter_command_rule_empty_ - extern void control_print_error_parameter_command_rule_empty(fll_program_data_t * const main, const f_string_static_t command) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_parameter_command_rule_empty_ +#ifndef _di_control_print_error_parameter_action_rule_directory_empty_ + extern void control_print_error_parameter_action_rule_directory_empty(fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d; +#endif // _di_control_print_error_parameter_action_rule_directory_empty_ /** - * Print an error message about the given parameter being a rule command but no rule name is specified. + * Print an error message about the given parameter being a rule action having an empty rule name. * * @param main * The main program data. - * @param command - * The parameter representing a command. + * @param action + * The parameter representing a action. */ -#ifndef _di_control_print_error_parameter_command_rule_not_ - extern void control_print_error_parameter_command_rule_not(fll_program_data_t * const main, const f_string_static_t command) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_parameter_command_rule_not_ +#ifndef _di_control_print_error_parameter_action_rule_empty_ + extern void control_print_error_parameter_action_rule_empty(fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d; +#endif // _di_control_print_error_parameter_action_rule_empty_ /** - * Print an error message about the given parameter being a rule command having too many arguments passed. + * Print an error message about the given parameter being a rule action but no rule name is specified. * * @param main * The main program data. - * @param command - * The parameter representing a command. + * @param action + * The parameter representing a action. */ -#ifndef _di_control_print_error_parameter_command_rule_too_many_ - extern void control_print_error_parameter_command_rule_too_many(fll_program_data_t * const main, const f_string_static_t command) F_attribute_visibility_internal_d; -#endif // _di_control_print_error_parameter_command_rule_too_many_ +#ifndef _di_control_print_error_parameter_action_rule_not_ + extern void control_print_error_parameter_action_rule_not(fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d; +#endif // _di_control_print_error_parameter_action_rule_not_ + +/** + * Print an error message about the given parameter being a rule action having too many arguments passed. + * + * @param main + * The main program data. + * @param action + * The parameter representing a action. + */ +#ifndef _di_control_print_error_parameter_action_rule_too_many_ + extern void control_print_error_parameter_action_rule_too_many(fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d; +#endif // _di_control_print_error_parameter_action_rule_too_many_ /** * Print an error message about the parameter's associated value being an empty string. @@ -196,6 +212,20 @@ extern "C" { extern void control_print_signal_received(fll_program_data_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; #endif // _di_control_print_signal_received_ +/** + * Print a warning message about a response header being repeated (when debugging). + * + * This program currently does not support multiple headers for any given valid header Object. + * + * @param main + * The main program data. + * @param response_header + * The repeated response header. + */ +#ifndef _di_control_print_warning_packet_header_duplicate_object_ + extern void control_print_warning_packet_header_duplicate_object(fll_program_data_t * const main, const f_string_static_t response_header) F_attribute_visibility_internal_d; +#endif // _di_control_print_warning_packet_header_duplicate_object_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/control/data/build/dependencies b/level_3/control/data/build/dependencies index 7af7025..8dc698b 100644 --- a/level_3/control/data/build/dependencies +++ b/level_3/control/data/build/dependencies @@ -14,6 +14,7 @@ f_pipe f_print f_signal f_socket +f_status_string fl_fss fl_print fl_string @@ -21,3 +22,4 @@ fll_error fll_fss fll_print fll_program +fll_status_string diff --git a/level_3/control/data/build/settings b/level_3/control/data/build/settings index ceddc44..9be56e0 100644 --- a/level_3/control/data/build/settings +++ b/level_3/control/data/build/settings @@ -22,7 +22,7 @@ build_indexer ar build_indexer_arguments rcs build_language c build_libraries -lc -build_libraries-individual -lfll_error -lfll_fss -lfll_print -lfll_program -lfl_conversion -lfl_fss -lfl_print -lfl_string -lf_color -lf_console -lf_conversion -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_socket -lf_status_string -lf_string -lf_type_array -lf_utf +build_libraries-individual -lfll_error -lfll_fss -lfll_print -lfll_program -lfll_status_string -lfl_conversion -lfl_fss -lfl_print -lfl_string -lf_color -lf_console -lf_conversion -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_socket -lf_status_string -lf_string -lf_type_array -lf_utf build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll build_libraries_shared diff --git a/level_3/controller/c/controller.h b/level_3/controller/c/controller.h index 5d45af8..c8aa7c9 100644 --- a/level_3/controller/c/controller.h +++ b/level_3/controller/c/controller.h @@ -50,6 +50,7 @@ #include #include #include +#include // FLL-1 includes. #include @@ -71,6 +72,7 @@ #include #include #include +#include // Controller includes. #include diff --git a/level_3/controller/c/lock/private-lock.h b/level_3/controller/c/lock/private-lock.h index 5c78ddf..2f31832 100644 --- a/level_3/controller/c/lock/private-lock.h +++ b/level_3/controller/c/lock/private-lock.h @@ -46,7 +46,6 @@ extern "C" { * * @return * F_none on success. - * F_status if main thread is disabled and write lock was never achieved. * * F_interrupt (with error bit set) on (exit) signal received, lock will not be set when this is returned. * @@ -123,7 +122,6 @@ extern "C" { * * @return * F_none on success. - * F_status if main thread is disabled and write lock was never achieved. * * F_interrupt (with error bit set) on (exit) signal received, lock will not be set when this is returned. * diff --git a/level_3/controller/data/build/dependencies b/level_3/controller/data/build/dependencies index ddf1abe..cc047e0 100644 --- a/level_3/controller/data/build/dependencies +++ b/level_3/controller/data/build/dependencies @@ -23,6 +23,7 @@ f_pipe f_print f_signal f_socket +f_status_string f_thread fl_control_group fl_conversion @@ -38,3 +39,4 @@ fll_fss fll_path fll_print fll_program +fll_status_string diff --git a/level_3/controller/data/build/settings b/level_3/controller/data/build/settings index 67b7a5b..ea1adf9 100644 --- a/level_3/controller/data/build/settings +++ b/level_3/controller/data/build/settings @@ -22,7 +22,7 @@ build_indexer ar build_indexer_arguments rcs build_language c build_libraries -lc -lcap -build_libraries-individual -lfll_control_group -lfll_error -lfll_execute -lfll_fss -lfll_path -lfll_print -lfll_program +build_libraries-individual -lfll_control_group -lfll_error -lfll_execute -lfll_fss -lfll_path -lfll_print -lfll_program -lfll_status_string build_libraries-individual -lfl_control_group -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_iki -lfl_print -lfl_string build_libraries-individual -lf_account -lf_capability -lf_color -lf_console -lf_control_group -lf_conversion -lf_directory -lf_environment -lf_execute -lf_file -lf_fss -lf_iki -lf_limit -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_socket -lf_status_string -lf_string -lf_thread -lf_type_array -lf_utf build_libraries-level -lfll_2 -lfll_1 -lfll_0