From c306c26879c2b994a252c1c7e24abc4f0a36ea55 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Sat, 2 Apr 2022 17:48:44 -0500 Subject: [PATCH] Update: Get the control program in a better state and update the control/controller documentation. I started realizing that there were things that I forgot all about that the control and controller programs need to do. This is too many changes to make immediately before the release. Wrap up the control program into a tolerable state and it will be published as is. Release notes will be used to document that this program didn't make the cut in time. --- level_3/control/c/common.h | 2 +- level_3/control/c/private-common.c | 3 + level_3/control/c/private-common.h | 9 + level_3/control/c/private-control.c | 350 +++++++++++--------------- level_3/control/c/private-control.h | 53 ++-- level_3/control/c/private-print.c | 66 +++++ level_3/control/c/private-print.h | 65 ++++- level_3/control/documents/packet_request.txt | 34 +++ level_3/control/documents/packet_response.txt | 16 +- level_3/controller/documents/packet.txt | 2 +- level_3/controller/specifications/packet.txt | 2 +- 11 files changed, 342 insertions(+), 260 deletions(-) create mode 100644 level_3/control/documents/packet_request.txt diff --git a/level_3/control/c/common.h b/level_3/control/c/common.h index 7c86200..7bd59a9 100644 --- a/level_3/control/c/common.h +++ b/level_3/control/c/common.h @@ -184,7 +184,7 @@ extern "C" { * Identify the action code the given name represents. * * @param action - * The string representing a action. + * The string representing an action. * * @return * The action type code on success. diff --git a/level_3/control/c/private-common.c b/level_3/control/c/private-common.c index 4c62cf9..40d4f54 100644 --- a/level_3/control/c/private-common.c +++ b/level_3/control/c/private-common.c @@ -17,13 +17,16 @@ 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_at_s = macro_f_string_static_t_initialize(CONTROL_at_s, 0, CONTROL_at_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_in_s = macro_f_string_static_t_initialize(CONTROL_in_s, 0, CONTROL_in_s_length); const f_string_static_t control_init_s = macro_f_string_static_t_initialize(CONTROL_init_s, 0, CONTROL_init_s_length); const f_string_static_t control_kexec_s = macro_f_string_static_t_initialize(CONTROL_kexec_s, 0, CONTROL_kexec_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_now_s = macro_f_string_static_t_initialize(CONTROL_now_s, 0, CONTROL_now_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); const f_string_static_t control_path_socket_prefix_s = macro_f_string_static_t_initialize(CONTROL_path_socket_prefix_s, 0, CONTROL_path_socket_prefix_s_length); const f_string_static_t control_path_socket_suffix_s = macro_f_string_static_t_initialize(CONTROL_path_socket_suffix_s, 0, CONTROL_path_socket_suffix_s_length); diff --git a/level_3/control/c/private-common.h b/level_3/control/c/private-common.h index 19b9ed8..649133e 100644 --- a/level_3/control/c/private-common.h +++ b/level_3/control/c/private-common.h @@ -128,13 +128,16 @@ extern "C" { #endif // defined(_override_control_path_settings_) && defined(_override_control_path_settings_length_) #define CONTROL_action_s "action" + #define CONTROL_at_s "at" #define CONTROL_controller_s "controller" #define CONTROL_default_s "default" #define CONTROL_error_s "error" #define CONTROL_kexec_s "kexec" + #define CONTROL_in_s "in" #define CONTROL_init_s "init" #define CONTROL_length_s "length" #define CONTROL_name_socket_s "name_socket" + #define CONTROL_now_s "now" #define CONTROL_path_socket_s "path_socket" #define CONTROL_path_socket_prefix_s "path_socket_prefix" #define CONTROL_path_socket_suffix_s "path_socket_suffix" @@ -155,13 +158,16 @@ extern "C" { #define CONTROL_thaw_s "thaw" #define CONTROL_action_s_length 6 + #define CONTROL_at_s_length 2 #define CONTROL_controller_s_length 10 #define CONTROL_default_s_length 7 #define CONTROL_error_s_length 5 + #define CONTROL_in_s_length 2 #define CONTROL_init_s_length 4 #define CONTROL_kexec_s_length 5 #define CONTROL_length_s_length 6 #define CONTROL_name_socket_s_length 11 + #define CONTROL_now_s_length 3 #define CONTROL_path_socket_s_length 11 #define CONTROL_path_socket_prefix_s_length 18 #define CONTROL_path_socket_suffix_s_length 18 @@ -184,13 +190,16 @@ 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_at_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_in_s; extern const f_string_static_t control_init_s; extern const f_string_static_t control_kexec_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_now_s; extern const f_string_static_t control_path_socket_s; extern const f_string_static_t control_path_socket_prefix_s; extern const f_string_static_t control_path_socket_suffix_s; diff --git a/level_3/control/c/private-control.c b/level_3/control/c/private-control.c index da49a2f..9e3c30f 100644 --- a/level_3/control/c/private-control.c +++ b/level_3/control/c/private-control.c @@ -21,19 +21,49 @@ extern "C" { case control_action_type_start_e: case control_action_type_stop_e: case control_action_type_thaw_e: - if (main->parameters.remaining.used < 2) { + if (main->parameters.remaining.used < 3) { 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_action_rule_too_many(main, data->argv[main->parameters.remaining.array[0]]); - return F_status_set_error(F_parameter); + if (main->parameters.remaining.used > 3) { + if (fl_string_dynamic_compare(control_at_s, data->argv[main->parameters.remaining.array[3]]) == F_equal_to) { + if (main->parameters.remaining.used < 5) { + control_print_error_parameter_action_rule_too_few_with(main, data->argv[main->parameters.remaining.array[0]], control_at_s); + + return F_status_set_error(F_parameter); + } + + if (main->parameters.remaining.used > 5) { + control_print_error_parameter_action_rule_too_many_with(main, data->argv[main->parameters.remaining.array[0]], control_at_s); + + return F_status_set_error(F_parameter); + } + } + else if (fl_string_dynamic_compare(control_in_s, data->argv[main->parameters.remaining.array[3]]) == F_equal_to) { + if (main->parameters.remaining.used < 6) { + control_print_error_parameter_action_rule_too_few_with(main, data->argv[main->parameters.remaining.array[0]], control_in_s); + + return F_status_set_error(F_parameter); + } + } + else if (fl_string_dynamic_compare(control_now_s, data->argv[main->parameters.remaining.array[3]]) == F_equal_to) { + if (main->parameters.remaining.used > 4) { + control_print_error_parameter_action_rule_too_many_with(main, data->argv[main->parameters.remaining.array[0]], control_now_s); + + return F_status_set_error(F_parameter); + } + } + else { + control_print_error_parameter_action_rule_with_unknown(main, data->argv[main->parameters.remaining.array[0]], data->argv[main->parameters.remaining.array[2]]); + + return F_status_set_error(F_parameter); + } } if (!data->argv[main->parameters.remaining.array[1]].used) { - if (main->parameters.remaining.used == 2) { + if (main->parameters.remaining.used == 3) { control_print_error_parameter_action_rule_empty(main, data->argv[main->parameters.remaining.array[0]]); } else { @@ -52,36 +82,95 @@ extern "C" { } return F_none; + + case control_action_type_kexec_e: + case control_action_type_reboot_e: + case control_action_type_shutdown_e: + if (main->parameters.remaining.used < 2) { + control_print_error_parameter_action_rule_too_few(main, data->argv[main->parameters.remaining.array[0]]); + + return F_status_set_error(F_parameter); + } + + if (fl_string_dynamic_compare(control_at_s, data->argv[main->parameters.remaining.array[1]]) == F_equal_to) { + if (main->parameters.remaining.used < 3) { + control_print_error_parameter_action_rule_too_few_with(main, data->argv[main->parameters.remaining.array[0]], control_at_s); + + return F_status_set_error(F_parameter); + } + + if (main->parameters.remaining.used > 3) { + control_print_error_parameter_action_rule_too_many_with(main, data->argv[main->parameters.remaining.array[0]], control_at_s); + + return F_status_set_error(F_parameter); + } + } + else if (fl_string_dynamic_compare(control_in_s, data->argv[main->parameters.remaining.array[1]]) == F_equal_to) { + if (main->parameters.remaining.used < 4) { + control_print_error_parameter_action_rule_too_few_with(main, data->argv[main->parameters.remaining.array[0]], control_in_s); + + return F_status_set_error(F_parameter); + } + } + else if (fl_string_dynamic_compare(control_now_s, data->argv[main->parameters.remaining.array[1]]) == F_equal_to) { + if (main->parameters.remaining.used > 2) { + control_print_error_parameter_action_rule_too_many_with(main, data->argv[main->parameters.remaining.array[0]], control_now_s); + + return F_status_set_error(F_parameter); + } + } + else { + control_print_error_parameter_action_rule_with_unknown(main, data->argv[main->parameters.remaining.array[0]], data->argv[main->parameters.remaining.array[1]]); + + return F_status_set_error(F_parameter); + } } - // Handle "kexec", "reboot", and "shutdown". - // @todo the reboot and shutdown need to support date and time actions: "now", "in (a time)", and "at (a time)". - return F_status_set_error(F_supported_not); + return F_none; } #endif // _di_control_action_verify_ #ifndef _di_control_packet_build_ f_status_t control_packet_build(const fll_program_data_t * const main, control_data_t * const data) { + data->cache.packet.used = 0; data->cache.large.used = 0; data->cache.small.used = 0; f_array_length_t i = 0; - f_array_length_t length = 5 + f_fss_string_header_s.used + f_fss_string_payload_s.used + control_action_s.used + control_type_s.used; - length += f_fss_payload_list_open_s.used * 2; - length += f_fss_payload_list_close_s.used * 4; - length += f_string_ascii_0_s.used; + f_status_t status = F_none; - for (; i < main->parameters.remaining.used; ++i) { - length += f_fss_payload_header_open_s.used + data->argv[main->parameters.remaining.array[i]].used + f_fss_payload_header_close_s.used; - } // for + { + f_array_length_t length = 5 + f_fss_string_header_s.used + f_fss_string_payload_s.used; + length += control_action_s.used + control_length_s.used + control_type_s.used; + length += (f_fss_payload_list_open_s.used + f_fss_payload_list_close_s.used) * 2; + length += (f_fss_payload_header_open_s.used + f_fss_payload_header_close_s.used) * 3; + length += data->argv[main->parameters.remaining.array[0]].used + f_string_ascii_0_s.used; + + // @todo This should properly handle escaping the FSS-0001 (Extended) Content and then count that length. + for (i = 1; i < main->parameters.remaining.used; ++i) { + length += f_fss_payload_header_next_s.used + data->argv[main->parameters.remaining.array[i]].used; + } // for + + if (data->action == control_action_type_kexec_e || data->action == control_action_type_reboot_e || data->action == control_action_type_shutdown_e) { + length += control_init_s.used; + } + else { + length += control_controller_s.used; + } + + if (length > 0xffffffffu) { + return F_status_set_error(F_too_large); + } - if (length > 0xffffffffu) { - return F_status_set_error(F_too_large); + status = f_string_dynamic_resize(length, &data->cache.packet); + if (F_status_is_error(status)) return status; } - f_status_t status = f_string_dynamic_resize(length, &data->cache.large); - if (F_status_is_error(status)) return status; + const f_state_t state = macro_f_state_t_initialize(control_allocation_large_d, control_allocation_small_d, 0, &fll_program_standard_signal_state, 0, (void *) main, 0); + + f_string_static_t contents_array[main->parameters.remaining.used]; + f_string_statics_t contents = macro_f_string_statics_t_initialize(contents_array, 0, main->parameters.remaining.used); // The Packet Control Block. { @@ -91,79 +180,63 @@ extern "C" { block_control |= (f_char_t) control_packet_flag_endian_big_d; #endif // _is_F_endian_big - status = f_string_append(&block_control, 1, &data->cache.large); + status = f_string_append(&block_control, 1, &data->cache.packet); if (F_status_is_error(status)) return status; } - // The Packet Size Block. - { - status = f_string_append((f_char_t *) &length, 1, &data->cache.large); - if (F_status_is_error(status)) return status; - } - - // The Payload "header:" line. - status = f_string_dynamic_append(f_fss_string_header_s, &data->cache.large); - if (F_status_is_error(status)) return status; - - status = f_string_dynamic_append(f_fss_payload_list_open_s, &data->cache.large); - if (F_status_is_error(status)) return status; - - status = f_string_dynamic_append(f_fss_payload_list_close_s, &data->cache.large); - if (F_status_is_error(status)) return status; + // Reserve the Packet Size Block to be calculated later. + data->cache.packet.used = 5; - // The Payload "type ..." line. - status = f_string_dynamic_append(control_type_s, &data->cache.large); - if (F_status_is_error(status)) return status; + // Payload Header: type. + if (data->action == control_action_type_kexec_e || data->action == control_action_type_reboot_e || data->action == control_action_type_shutdown_e) { + contents_array[0] = control_init_s; + } + else { + contents_array[0] = control_controller_s; + } - status = f_string_dynamic_append(f_fss_payload_header_open_s, &data->cache.large); - if (F_status_is_error(status)) return status; + contents.used = 1; - status = f_string_dynamic_append(data->argv[main->parameters.remaining.array[0]], &data->cache.large); + status = fll_fss_extended_write_string(control_type_s, contents, 0, state, &data->cache.large); if (F_status_is_error(status)) return status; - status = f_string_dynamic_append(f_fss_payload_header_close_s, &data->cache.large); - if (F_status_is_error(status)) return status; - - // Each Payload "action ..." line. - for (i = 1; i < main->parameters.remaining.used; ++i) { - - status = f_string_dynamic_append(control_action_s, &data->cache.large); - if (F_status_is_error(status)) return status; - - status = f_string_dynamic_append(f_fss_payload_header_open_s, &data->cache.large); - if (F_status_is_error(status)) return status; - - status = f_string_dynamic_append(data->argv[main->parameters.remaining.array[i]], &data->cache.large); - if (F_status_is_error(status)) return status; - - status = f_string_dynamic_append(f_fss_payload_header_close_s, &data->cache.large); - if (F_status_is_error(status)) return status; + // Payload Header: action. + for (contents.used = 0; contents.used < main->parameters.remaining.used; ++contents.used) { + contents_array[contents.used] = data->argv[main->parameters.remaining.array[contents.used]]; } // for - // The Payload "length 0" line. - status = f_string_dynamic_append(control_length_s, &data->cache.large); + status = fll_fss_extended_write_string(control_action_s, contents, 0, state, &data->cache.large); if (F_status_is_error(status)) return status; - status = f_string_dynamic_append(f_fss_payload_header_open_s, &data->cache.large); - if (F_status_is_error(status)) return status; - - status = f_string_dynamic_append(f_string_ascii_0_s, &data->cache.large); - if (F_status_is_error(status)) return status; + // Payload Header: length. + contents_array[0] = f_string_ascii_0_s; + contents.used = 1; - status = f_string_dynamic_append(f_fss_payload_header_close_s, &data->cache.large); + status = fll_fss_extended_write_string(control_length_s, contents, 0, state, &data->cache.large); if (F_status_is_error(status)) return status; - // The Payload "payload:" line. - status = f_string_dynamic_append(f_fss_string_payload_s, &data->cache.large); + // Payload Packet: Header. + status = fll_fss_payload_write_string(f_fss_string_header_s, data->cache.large, F_false, 0, state, &data->cache.packet); if (F_status_is_error(status)) return status; - status = f_string_dynamic_append(f_fss_payload_list_open_s, &data->cache.large); - if (F_status_is_error(status)) return status; + // Payload Packet: Payload. + data->cache.large.used = 0; - status = f_string_dynamic_append(f_fss_payload_list_open_end_s, &data->cache.large); + status = fll_fss_payload_write_string(f_fss_string_payload_s, data->cache.large, F_false, 0, state, &data->cache.packet); if (F_status_is_error(status)) return status; - // The Payload "payload:" Content is empty. + // Construct Packet Size Block. + #ifdef _is_F_endian_big + data->cache.packet.string[1] = data->cache.packet.used & 0xffu; + data->cache.packet.string[2] = data->cache.packet.used & 0xff00u; + data->cache.packet.string[3] = data->cache.packet.used & 0xff0000u; + data->cache.packet.string[4] = data->cache.packet.used & 0xff000000u; + #else + data->cache.packet.string[1] = data->cache.packet.used & 0xff000000u; + data->cache.packet.string[2] = data->cache.packet.used & 0xff0000u; + data->cache.packet.string[3] = data->cache.packet.used & 0xff00u; + data->cache.packet.string[4] = data->cache.packet.used & 0xffu; + #endif // _is_F_endian_big return F_none; } @@ -530,145 +603,12 @@ extern "C" { #ifndef _di_control_packet_send_ f_status_t control_packet_send(const fll_program_data_t * const main, control_data_t * const data) { - { - f_status_t status = F_none; - f_string_dynamic_t payload = f_string_dynamic_t_initialize; - - 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: - payload = data->argv[main->parameters.remaining.array[1]]; - break; - - default: - // @todo construct message for kexec, reboot, and shutdown. - break; - } - - status = control_packet_send_build(main, data, control_controller_s, control_action_type_name(data->action), f_string_empty_s, payload); - - f_string_dynamic_resize(0, &payload); - - if (F_status_is_error(status)) return status; - } - data->socket.size_write = data->cache.packet.used; return f_socket_write(&data->socket, 0, (void *) &data->cache.packet, 0); } #endif // _di_control_packet_send_ -#ifndef _di_control_packet_send_build_ - f_status_t control_packet_send_build(const fll_program_data_t * const main, control_data_t * const data, const f_string_static_t type, const f_string_static_t action, const f_string_static_t status, const f_string_static_t payload) { - - f_status_t status2 = F_none; - - const f_state_t state = f_state_t_initialize; - const f_conversion_data_t data_conversion = macro_f_conversion_data_t_initialize(10, 0, 1); - - f_string_statics_t content = f_string_statics_t_initialize; - f_string_static_t contents[1]; - content.array = contents; - content.used = 1; - - data->cache.large.used = 0; - data->cache.small.used = 0; - data->cache.packet.used = 0; - - // Reserve space in data->cache.packet.size for the packet header as well as other parts. - { - // 5 for packet header and 2 for ':\n" for both 'header' and 'payload'. - f_array_length_t total = 9 + f_fss_string_header_s.used + f_fss_string_payload_s.used + control_length_s.used + payload.used; - - if (type.used) { - total += control_type_s.used + type.used + 2; - } - - if (action.used) { - total += control_action_s.used + action.used + 2; - } - - if (status.used) { - total += control_status_s.used + status.used + 2; - } - - status2 = f_string_dynamic_increase_by(total, &data->cache.packet); - } - - #ifdef _is_F_endian_big - data->cache.packet.string[0] = control_packet_flag_endian_big_d; - #else - data->cache.packet.string[0] = 0; - #endif // _is_F_endian_big - - data->cache.packet.used = 5; - - // Payload Header: type. - if (type.used) { - contents[0] = type; - - status2 = fll_fss_extended_write_string(control_type_s, content, 0, state, &data->cache.large); - if (F_status_is_error(status2)) return status2; - } - - // Payload Header: action. - if (action.used) { - contents[0] = action; - - status2 = fll_fss_extended_write_string(control_action_s, content, 0, state, &data->cache.large); - if (F_status_is_error(status2)) return status2; - } - - // Payload Header: status. - if (status.used) { - contents[0] = status; - - status2 = fll_fss_extended_write_string(control_status_s, content, 0, state, &data->cache.large); - if (F_status_is_error(status2)) return status2; - } - - // Payload Header: length. - status2 = f_conversion_number_unsigned_to_string(payload.used, data_conversion, &data->cache.small); - if (F_status_is_error(status2)) return status2; - - contents[0] = data->cache.small; - - status2 = fll_fss_extended_write_string(control_length_s, content, 0, state, &data->cache.large); - if (F_status_is_error(status2)) return status2; - - // Payload Packet: Header. - status2 = fll_fss_payload_write_string(f_fss_string_header_s, data->cache.large, F_false, 0, state, &data->cache.packet); - if (F_status_is_error(status2)) return status2; - - // Payload Packet: Payload. - status2 = fll_fss_payload_write_string(f_fss_string_payload_s, payload, F_false, 0, state, &data->cache.packet); - if (F_status_is_error(status2)) return status2; - - // Construct packet size. - #ifdef _is_F_endian_big - data->cache.packet.string[1] = data->cache.packet.used & 0xffu; - data->cache.packet.string[2] = data->cache.packet.used & 0xff00u; - data->cache.packet.string[3] = data->cache.packet.used & 0xff0000u; - data->cache.packet.string[4] = data->cache.packet.used & 0xff000000u; - #else - data->cache.packet.string[1] = data->cache.packet.used & 0xff000000u; - data->cache.packet.string[2] = data->cache.packet.used & 0xff0000u; - data->cache.packet.string[3] = data->cache.packet.used & 0xff00u; - data->cache.packet.string[4] = data->cache.packet.used & 0xffu; - #endif // _is_F_endian_big - - return F_none; - } -#endif // _di_control_packet_send_build_ - #ifndef _di_control_settings_load_ f_status_t control_settings_load(const fll_program_data_t * const main, control_data_t * const data) { diff --git a/level_3/control/c/private-control.h b/level_3/control/c/private-control.h index 7a303f4..64429fb 100644 --- a/level_3/control/c/private-control.h +++ b/level_3/control/c/private-control.h @@ -19,6 +19,11 @@ extern "C" { * The main program data. * @param data * The control data. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) on parameter validation/verification failure. */ #ifndef _di_control_action_verify_ extern f_status_t control_action_verify(const fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d; @@ -40,6 +45,8 @@ extern "C" { * Errors (with error bit) from: f_string_append(). * Errors (with error bit) from: f_string_dynamic_append(). * Errors (with error bit) from: f_string_dynamic_resize(). + * Errors (with error bit) from: fll_fss_extended_write_string(). + * Errors (with error bit) from: fll_fss_payload_write_string(). * * @see f_string_append() * @see f_string_dynamic_append() @@ -136,6 +143,7 @@ extern "C" { * * F_busy (with error bit) * F_failure (with error bit) on success but controller returned failure for action. + * F_known_not (with error bit) if the Payload type is unknown. * Any error (with error bit) on failure where the error is defined by the controller service. */ #ifndef _di_control_packet_process_ @@ -149,51 +157,18 @@ extern "C" { * The main program data. * @param data * The control data. - */ -#ifndef _di_control_packet_send_ - extern f_status_t control_packet_send(const fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d; -#endif // _di_control_packet_send_ - -/** - * Construct the entire payload. - * - * This resets and uses data->cache.small, data->cache.large, and data->cache.packet. - * Do not use any of these for passing strings to this function. - * - * The results of this function replaces data->cache.packet. - * - * @param global - * The global data. - * @param data - * The control data. - * @param type - * The packet type. - * Set type.used to 0 to not add to the header. - * @param action - * The action code. - * Set action.used to 0 to not add to the header. - * @param status - * The status code. - * Set status.used to 0 to not add to the header. - * @param payload - * The payload Content. * * @return * F_none on success. * - * Errors (with error bit) from: f_conversion_number_unsigned_to_string(). - * Errors (with error bit) from: f_string_append(). - * Errors (with error bit) from: fll_fss_extended_write_string(). - * Errors (with error bit) from: fll_fss_payload_write_string(). + * Errors (with error bit) from: f_socket_write(). * - * @see f_conversion_number_unsigned_to_string() - * @see f_string_append() - * @see fll_fss_extended_write_string() - * @see fll_fss_payload_write_string() + * @see f_socket_write() */ -#ifndef _di_control_packet_send_build_ - extern f_status_t control_packet_send_build(const fll_program_data_t * const main, control_data_t * const data, const f_string_static_t type, const f_string_static_t action, const f_string_static_t status, const f_string_static_t payload) F_attribute_visibility_internal_d; -#endif // _di_control_packet_send_build_ +#ifndef _di_control_packet_send_ + extern f_status_t control_packet_send(const fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d; +#endif // _di_control_packet_send_ + /** * Load and process the control settings file. * diff --git a/level_3/control/c/private-print.c b/level_3/control/c/private-print.c index 9acb7ec..4963f40 100644 --- a/level_3/control/c/private-print.c +++ b/level_3/control/c/private-print.c @@ -224,6 +224,38 @@ extern "C" { } #endif // _di_control_print_error_parameter_action_rule_not_ +#ifndef _di_control_print_error_parameter_action_rule_too_few_ + void control_print_error_parameter_action_rule_too_few(const 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 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 few 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_action_rule_too_few_ + +#ifndef _di_control_print_error_parameter_action_rule_too_few_with_ + void control_print_error_parameter_action_rule_too_few_with(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) { + + if (main->error.verbosity == f_console_verbosity_quiet_e) return; + + flockfile(main->error.to.stream); + + 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("%[' when used with '%]", 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, with, main->context.set.notable); + fl_print_format("%[' has too few 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_action_rule_too_few_with_ + #ifndef _di_control_print_error_parameter_action_rule_too_many_ void control_print_error_parameter_action_rule_too_many(const fll_program_data_t * const main, const f_string_static_t action) { @@ -239,6 +271,40 @@ extern "C" { } #endif // _di_control_print_error_parameter_action_rule_too_many_ +#ifndef _di_control_print_error_parameter_action_rule_too_many_with_ + void control_print_error_parameter_action_rule_too_many_with(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) { + + if (main->error.verbosity == f_console_verbosity_quiet_e) return; + + flockfile(main->error.to.stream); + + 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("%[' when used with '%]", 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, with, 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_action_rule_too_many_with_ + +#ifndef _di_control_print_error_parameter_action_rule_with_unknown_ + void control_print_error_parameter_action_rule_with_unknown(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) { + + if (main->error.verbosity == f_console_verbosity_quiet_e) return; + + flockfile(main->error.to.stream); + + 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("%[' does not know the argument '%]", 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, with, main->context.set.notable); + fl_print_format("%['.%]%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_action_rule_with_unknown_ + #ifndef _di_control_print_error_parameter_value_empty_ void control_print_error_parameter_value_empty(const fll_program_data_t * const main, const f_string_static_t parameter) { diff --git a/level_3/control/c/private-print.h b/level_3/control/c/private-print.h index 23f3d2e..a7f6217 100644 --- a/level_3/control/c/private-print.h +++ b/level_3/control/c/private-print.h @@ -99,7 +99,7 @@ extern "C" { * @param main * The main program data. * @param action - * The parameter representing a action. + * The parameter representing an action. */ #ifndef _di_control_print_error_parameter_action_not_ extern void control_print_error_parameter_action_not(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d; @@ -111,7 +111,7 @@ extern "C" { * @param main * The main program data. * @param action - * The parameter representing a action. + * The parameter representing an action. */ #ifndef _di_control_print_error_parameter_action_rule_basename_empty_ extern void control_print_error_parameter_action_rule_basename_empty(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d; @@ -123,7 +123,7 @@ extern "C" { * @param main * The main program data. * @param action - * The parameter representing a action. + * The parameter representing an action. */ #ifndef _di_control_print_error_parameter_action_rule_directory_empty_ extern void control_print_error_parameter_action_rule_directory_empty(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d; @@ -135,7 +135,7 @@ extern "C" { * @param main * The main program data. * @param action - * The parameter representing a action. + * The parameter representing an action. */ #ifndef _di_control_print_error_parameter_action_rule_empty_ extern void control_print_error_parameter_action_rule_empty(const fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d; @@ -147,25 +147,78 @@ extern "C" { * @param main * The main program data. * @param action - * The parameter representing a action. + * The parameter representing an action. */ #ifndef _di_control_print_error_parameter_action_rule_not_ extern void control_print_error_parameter_action_rule_not(const 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 few arguments passed. + * + * @param main + * The main program data. + * @param action + * The parameter representing an action. + */ +#ifndef _di_control_print_error_parameter_action_rule_too_few_ + extern void control_print_error_parameter_action_rule_too_few(const 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_few_ + +/** + * Print an error message about the given parameter being a rule action having few many arguments passed for a given "with". + * + * @param main + * The main program data. + * @param action + * The parameter representing an action. + * @param with + * The additional parameter in which is requiring additional arguments that are not met. + */ +#ifndef _di_control_print_error_parameter_action_rule_too_few_with_ + extern void control_print_error_parameter_action_rule_too_few_with(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) F_attribute_visibility_internal_d; +#endif // _di_control_print_error_parameter_action_rule_too_few_with_ + +/** * 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. + * The parameter representing an action. */ #ifndef _di_control_print_error_parameter_action_rule_too_many_ extern void control_print_error_parameter_action_rule_too_many(const 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 given parameter being a rule action having too many arguments passed for a given "with". + * + * @param main + * The main program data. + * @param action + * The parameter representing an action. + * @param with + * The additional parameter in which is requiring additional arguments that are not met. + */ +#ifndef _di_control_print_error_parameter_action_rule_too_many_with_ + extern void control_print_error_parameter_action_rule_too_many_with(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) F_attribute_visibility_internal_d; +#endif // _di_control_print_error_parameter_action_rule_too_many_with_ +/** + * Print an error message about the given parameter being unknown for the use with the given action. + * + * @param main + * The main program data. + * @param action + * The parameter representing an action. + * @param with + * The additional parameter in which is requiring additional arguments that are not met. + */ +#ifndef _di_control_print_error_parameter_action_rule_with_unknown_ + extern void control_print_error_parameter_action_rule_with_unknown(const fll_program_data_t * const main, const f_string_static_t action, const f_string_static_t with) F_attribute_visibility_internal_d; +#endif // _di_control_print_error_parameter_action_rule_with_unknown_ + +/** * Print an error message about the parameter's associated value being an empty string. * * @param main diff --git a/level_3/control/documents/packet_request.txt b/level_3/control/documents/packet_request.txt new file mode 100644 index 0000000..e3b98b1 --- /dev/null +++ b/level_3/control/documents/packet_request.txt @@ -0,0 +1,34 @@ +# fss-0002 + +Packet Request: + The control program sends packets and receives packet responses from the controller program over the controller program's control socket. + This documentation describes the request packets sent by this program. + + The purpose of these request packets are to ask the controller program to perform a requested action. + + The communications to/from the controller program utilize the FSS-000F (Simple Packet). + This Simple Packet is expected to contain within it the FSS-000E (Payload) format. + + The Payload contains within it a Header and a Payload. + Note the potential confusion here between the Payload when referring to the Packet format and the Payload referring to the Content within the Payload Packet. + To avoid this, henceforth "Payload Packet" refers to the FSS-000E (Payload) used within the FSS-000F (Simple Packet). + The "Payload Header" refers to eithe the Object ("header:") or Content within the Payload Packet representing the header. + The "Payload Object" refers to the Object within the Payload Packet (ie: "payload:"). + The "Payload Content" refers to the Content within the Payload Packet. + + The Payload Packet (FSS-000E) is very flexible in what it allows within the Header of the Payload Packet. + The Control program is more restrictive and supports only a subset of the possibilities (which this is explicitly allowed by the Specification). + + The Control program only supports the following Payload Packet header Objects for the request\: + - type: Allowing only a single type header Object and may only be one of: "controller", "error", or "init". + - length: Allowing only a single length header Object and must properly describe the length of the entire Payload Packet as per the referenced Specifications. + - action: Allowing only a single action header Object and whose first Content must only be one of: "freeze", "kexec", "kill", "pause", "reboot", "reload", "rerun", "restart", "resume", "shutdown", "start", "stop", and "thaw". + + The number of Content associated with a action are specific to the requirements of that action. + + The Payload Content is not used and should always be of length 0. + + The Payload Content represents the rule being started in FSS-0001 (Extended) format, such as "service sshd". + + For example, given the command: "control start service sshd in 5 minutes". + The "action" Object would be "start service sshd in 5 minutes". diff --git a/level_3/control/documents/packet_response.txt b/level_3/control/documents/packet_response.txt index 59de322..3c7dafb 100644 --- a/level_3/control/documents/packet_response.txt +++ b/level_3/control/documents/packet_response.txt @@ -4,20 +4,22 @@ Packet Response: The control program sends packets and receives packet responses from the controller program over the controller program's control socket. This documentation describes the expected response packets and how these response packets are handled. - The communications to/from the controller program utilize the FSS-000F (Simple Packet). + The communications to/from the controller program utilize the FSS-000F (Simple Packet). This Simple Packet is expected to contain within it the FSS-000E (Payload) format. The Payload contains within it a Header and a Payload. - Note the potential confusion here between the Payload when referring to the Packet data format and the Payload referring to the Content within the Payload Packet. - To avoid this, henceforth "Payload Packet" refers to the FSS-000E (Payload) format used within the Simple Packet and "Payload Content" refers to the Content within the Payload Packet. + Note the potential confusion here between the Payload when referring to the Packet format and the Payload referring to the Content within the Payload Packet. + The "Payload Header" refers to eithe the Object ("header:") or Content within the Payload Packet representing the header. + The "Payload Object" refers to the Object within the Payload Packet (ie: "payload:"). + The "Payload Content" refers to the Content within the Payload Packet. The Payload Packet (FSS-000E) is very flexible in what it allows within the Header of the Payload Packet. The Control program is more restrictive and supports only a subset of the possibilities (which this is explicitly allowed by the Specification). - The Control program only supports the following Payload Packet header Objects\: + The Control program only supports the following Payload Packet header Objects for the response\: - status: Allowing only a single status header Object. - - type: Allowing only a single type header Object and may only be one of: "controller", "error", or "kexec". - - action: Allowing only a single action header Object and may only be one of: "freeze", "kill", "pause", "reboot", "reload", "rerun", "restart", "resume", "shutdown", "start", "stop", and "thaw". + - type: Allowing only a single type header Object and may only be one of: "controller", "error", or "init". + - action: Allowing only a single action header Object and must only be one of: "freeze", "kexec", "kill", "pause", "reboot", "reload", "rerun", "restart", "resume", "shutdown", "start", "stop", and "thaw". - length: Allowing only a single length header Object and must properly describe the length of the entire Payload Packet as per the referenced Specifications. The "error" type response Payload Packet is treated as an error response. @@ -29,7 +31,7 @@ Packet Response: The "controller" type response Payload Packet represents a response regarding the result of performing a requested action. There must always be an "action" designating the action this response is in regards to. Only the following are (currently) supported as a status\: - - F_busy: When unable to perform the action as because the service is too busy or the + - F_busy: When unable to perform the action as because the service is too busy or the - F_done: When successfully performed the action but the action does not return success or failure. - F_failure: When successfully performed the action and the action returned some sort of failure or error. - F_success: When successfully performed the action and the action returned some sort of success. diff --git a/level_3/controller/documents/packet.txt b/level_3/controller/documents/packet.txt index 968b7ed..88c46b7 100644 --- a/level_3/controller/documents/packet.txt +++ b/level_3/controller/documents/packet.txt @@ -54,7 +54,7 @@ Packet Documentation: The "payload" is expected to be empty and have a length of 0 for a request. The "payload" may have an FSS-0000 (Basic) format containing a single Object "message" to represent a message associated with an action. - Multuple "message" may exist in the response so long as they each match an "action" in the request. + Multiple "message" may exist in the response so long as they each match an "action" in the request. The error payload\: The error payload is intended to communicate some sort of failure. diff --git a/level_3/controller/specifications/packet.txt b/level_3/controller/specifications/packet.txt index 1ce92c5..a290d20 100644 --- a/level_3/controller/specifications/packet.txt +++ b/level_3/controller/specifications/packet.txt @@ -16,7 +16,7 @@ Packet Specification: - size: A single 4-byte block representing the size of the entire packet, including the control block. The "header" Object contains the following FSS-0001 Extended Objects (depending on "type")\: - - action: A valid action type: "freeze", "kill", "pause", "reboot", "reload", "rerun", "restart", "resume", "shutdown", "start", "stop", or "thaw". + - action: A valid action type: "freeze", "kexec", "kill", "pause", "reboot", "reload", "rerun", "restart", "resume", "shutdown", "start", "stop", or "thaw". - length: A positive whole number inclusively between 0 and 4294965248 representing the length of the "payload" (may be in binary, octal, decimal, duodecimal, or hexidecimal). - status: The status code name or number representing an FSS status code, such as F_none, F_failure, or 200 (where a number may have error and warning bits and may be in binary, octal, decimal, duodecimal, or hexidecimal). - type: The packet type that is one of "controller", "error", or "init". -- 1.8.3.1