]> Kevux Git Server - fll/commitdiff
Progress: Controller and Control sockets.
authorKevin Day <thekevinday@gmail.com>
Fri, 18 Mar 2022 00:01:14 +0000 (19:01 -0500)
committerKevin Day <thekevinday@gmail.com>
Fri, 18 Mar 2022 00:01:14 +0000 (19:01 -0500)
level_3/control/c/common.c
level_3/control/c/common.h
level_3/control/c/control.c
level_3/control/c/private-control.c
level_3/control/c/private-control.h
level_3/control/c/private-print.c
level_3/control/c/private-print.h
level_3/control/documents/packet_response.txt [new file with mode: 0644]
specifications/fss-000f.txt

index 4109b4743e622b03dd0791fbadcc1b73ab32fdaa..11484261ef2e7cd71ba2cd1fcc59756e89a98e80 100644 (file)
@@ -1,4 +1,5 @@
 #include "control.h"
+#include "private-common.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -15,14 +16,76 @@ extern "C" {
 
 #ifndef _di_control_parameters_
   const f_string_static_t control_short_name_s = macro_f_string_static_t_initialize(CONTROL_short_name_s, 0, CONTROL_short_name_s_length);
+  const f_string_static_t control_short_return_s = macro_f_string_static_t_initialize(CONTROL_short_return_s, 0, CONTROL_short_return_s_length);
   const f_string_static_t control_short_settings_s = macro_f_string_static_t_initialize(CONTROL_short_settings_s, 0, CONTROL_short_settings_s_length);
   const f_string_static_t control_short_socket_s = macro_f_string_static_t_initialize(CONTROL_short_socket_s, 0, CONTROL_short_socket_s_length);
 
   const f_string_static_t control_long_name_s = macro_f_string_static_t_initialize(CONTROL_long_name_s, 0, CONTROL_long_name_s_length);
+  const f_string_static_t control_long_return_s = macro_f_string_static_t_initialize(CONTROL_long_return_s, 0, CONTROL_long_return_s_length);
   const f_string_static_t control_long_settings_s = macro_f_string_static_t_initialize(CONTROL_long_settings_s, 0, CONTROL_long_settings_s_length);
   const f_string_static_t control_long_socket_s = macro_f_string_static_t_initialize(CONTROL_long_socket_s, 0, CONTROL_long_socket_s_length);
 #endif // _di_control_parameters_
 
+#ifndef _di_control_action_type_name_
+  f_string_static_t control_action_type_name(const uint8_t type) {
+
+    switch (type) {
+      case control_action_type_freeze_e:
+        return control_freeze_s;
+
+      case control_action_type_kill_e:
+        return control_kill_s;
+
+      case control_action_type_pause_e:
+        return control_pause_s;
+
+      case control_action_type_reboot_e:
+        return control_reboot_s;
+
+      case control_action_type_reload_e:
+        return control_reload_s;
+
+      case control_action_type_rerun_e:
+        return control_rerun_s;
+
+      case control_action_type_restart_e:
+        return control_restart_s;
+
+      case control_action_type_resume_e:
+        return control_resume_s;
+
+      case control_action_type_shutdown_e:
+        return control_shutdown_s;
+
+      case control_action_type_start_e:
+        return control_start_s;
+
+      case control_action_type_stop_e:
+        return control_stop_s;
+
+      case control_action_type_thaw_e:
+        return control_thaw_s;
+    }
+
+    return f_string_empty_s;
+  }
+#endif // _di_control_action_type_name_
+
+#ifndef _di_control_payload_type_name_
+  f_string_static_t control_payload_type_name(const uint8_t type) {
+
+    switch (type) {
+      case control_payload_type_controller_e:
+        return control_controller_s;
+
+      case control_payload_type_error_e:
+        return control_error_s;
+    }
+
+    return f_string_empty_s;
+  }
+#endif // _di_control_payload_type_name_
+
 #ifndef _di_control_main_delete_
   f_status_t control_main_delete(fll_program_data_t * const main) {
 
index f323f954dc2c70b1a840c07eca0920f4f7b4759b..02261fa851810912cea1a3bf2a252727564e4821 100644 (file)
@@ -64,26 +64,32 @@ extern "C" {
  */
 #ifndef _di_control_parameters_
   #define CONTROL_short_name_s     "n"
+  #define CONTROL_short_return_s   "R"
   #define CONTROL_short_settings_s "s"
   #define CONTROL_short_socket_s   "k"
 
   #define CONTROL_long_name_s     "name"
+  #define CONTROL_long_return_s   "return"
   #define CONTROL_long_settings_s "settings"
   #define CONTROL_long_socket_s   "socket"
 
   #define CONTROL_short_name_s_length     1
+  #define CONTROL_short_return_s_length   1
   #define CONTROL_short_settings_s_length 1
   #define CONTROL_short_socket_s_length   1
 
   #define CONTROL_long_name_s_length     4
+  #define CONTROL_long_return_s_length   6
   #define CONTROL_long_settings_s_length 8
   #define CONTROL_long_socket_s_length   6
 
   extern const f_string_static_t control_short_name_s;
+  extern const f_string_static_t control_short_return_s;
   extern const f_string_static_t control_short_settings_s;
   extern const f_string_static_t control_short_socket_s;
 
   extern const f_string_static_t control_long_name_s;
+  extern const f_string_static_t control_long_return_s;
   extern const f_string_static_t control_long_settings_s;
   extern const f_string_static_t control_long_socket_s;
 
@@ -99,6 +105,7 @@ extern "C" {
     control_parameter_version_e,
 
     control_parameter_name_e,
+    control_parameter_return_e,
     control_parameter_settings_e,
     control_parameter_socket_e,
   };
@@ -115,14 +122,41 @@ extern "C" {
       macro_f_console_parameter_t_initialize(f_console_standard_short_debug_s.string, f_console_standard_long_debug_s.string, 0, 0, f_console_type_inverse_e), \
       macro_f_console_parameter_t_initialize(f_console_standard_short_version_s.string, f_console_standard_long_version_s.string, 0, 0, f_console_type_inverse_e), \
       macro_f_console_parameter_t_initialize(control_short_name_s.string, control_long_name_s.string, 0, 1, f_console_type_normal_e), \
+      macro_f_console_parameter_t_initialize(control_short_return_s.string, control_long_return_s.string, 0, 1, f_console_type_normal_e), \
       macro_f_console_parameter_t_initialize(control_short_settings_s.string, control_long_settings_s.string, 0, 1, f_console_type_normal_e), \
       macro_f_console_parameter_t_initialize(control_short_socket_s.string, control_long_socket_s.string, 0, 1, f_console_type_normal_e), \
     }
 
-  #define control_total_parameters_d 12
+  #define control_total_parameters_d 13
 #endif // _di_control_parameters_
 
 /**
+ * Get the name of the action type.
+ *
+ * @param type
+ *   The action type id.
+ *
+ * @return
+ *   The string associated with the action type.
+ */
+#ifndef _di_control_action_type_name_
+  extern f_string_static_t control_action_type_name(const uint8_t type);
+#endif // _di_control_action_type_name_
+
+/**
+ * Get the name of the payload type.
+ *
+ * @param type
+ *   The payload type id.
+ *
+ * @return
+ *   The string associated with the payload type.
+ */
+#ifndef _di_control_payload_type_name_
+  extern f_string_static_t control_payload_type_name(const uint8_t type);
+#endif // _di_control_payload_type_name_
+
+/**
  * Deallocate main.
  *
  * Be sure to call this after executing control_main().
index 36c55497332a089da5cf67232a25994c95e28b93..20fc04755912722a8ff1c09370ca71162926c624 100644 (file)
@@ -27,6 +27,7 @@ extern "C" {
     f_print_dynamic_raw(f_string_eol_s, main->output.to.stream);
 
     fll_program_print_help_option(main->output.to, main->context, control_short_name_s, control_long_name_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "    Specify the name of the controller socket file.");
+    fll_program_print_help_option(main->output.to, main->context, control_short_return_s, control_long_return_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "  Print a message about the response packet.");
     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.");
 
@@ -39,6 +40,10 @@ extern "C" {
     fl_print_format(" as a single parameter or two parameters with the first representing the rule directory path '%[boot%]'", main->output.to.stream, main->context.set.notable, main->context.set.notable);
     fl_print_format(" and the second representing the rule base name '%[root%]'.%r%r", main->output.to.stream, main->context.set.notable, main->context.set.notable, f_string_eol_s, f_string_eol_s);
 
+    fl_print_format("  The %[%r%r%] parameter is intended to be used for scripting and is of the form \"response [type] [action] [status]\".%r", main->output.to.stream, main->context.set.notable, f_console_symbol_long_enable_s, control_long_return_s, main->context.set.notable, f_string_eol_s);
+    fl_print_format("  Be sure to use the %[%r%r%] parameter to suppress output when using this in scripting.%r", main->output.to.stream, main->context.set.notable, f_console_symbol_long_disable_s, f_console_standard_long_quiet_s, main->context.set.notable, f_string_eol_s);
+    fl_print_format("  No response is returned on program errors, especially those errors that prevent communicating to the controller.%r%r", main->output.to.stream, f_string_eol_s, f_string_eol_s);
+
     fflush(main->output.to.stream);
     funlockfile(main->output.to.stream);
 
@@ -249,10 +254,13 @@ extern "C" {
               }
             }
             else {
-              status = control_packet_process(main, &data, header);
+              status = control_packet_process(main, &data, &header);
 
+              // Print the error message only if the error message is not already printed.
               if (F_status_is_error(status)) {
-                fll_error_print(main->error, F_status_set_fine(status), "control_packet_process", F_true);
+                if (header.type != control_payload_type_error_e && (header.type != control_payload_type_controller_e || F_status_set_fine(status) != header.status || (header.status != F_failure && header.status != F_busy))) {
+                  fll_error_print(main->error, F_status_set_fine(status), "control_packet_process", F_true);
+                }
               }
             }
           }
index 4f441a52fb928385c9ba63b9b29be03e2cbb66f8..fb27c05eeea139b2a8b8b3ca71ffb02fff620d74 100644 (file)
@@ -62,51 +62,6 @@ extern "C" {
   }
 #endif // _di_control_action_identify_
 
-#ifndef _di_control_action_type_name_
-  f_string_static_t control_action_type_name(const uint8_t type) {
-
-    switch (type) {
-      case control_action_type_freeze_e:
-        return control_freeze_s;
-
-      case control_action_type_kill_e:
-        return control_kill_s;
-
-      case control_action_type_pause_e:
-        return control_pause_s;
-
-      case control_action_type_reboot_e:
-        return control_reboot_s;
-
-      case control_action_type_reload_e:
-        return control_reload_s;
-
-      case control_action_type_rerun_e:
-        return control_rerun_s;
-
-      case control_action_type_restart_e:
-        return control_restart_s;
-
-      case control_action_type_resume_e:
-        return control_resume_s;
-
-      case control_action_type_shutdown_e:
-        return control_shutdown_s;
-
-      case control_action_type_start_e:
-        return control_start_s;
-
-      case control_action_type_stop_e:
-        return control_stop_s;
-
-      case control_action_type_thaw_e:
-        return control_thaw_s;
-    }
-
-    return f_string_empty_s;
-  }
-#endif // _di_control_action_type_name_
-
 #ifndef _di_control_action_verify_
   f_status_t control_action_verify(fll_program_data_t * const main, control_data_t * const data) {
 
@@ -599,17 +554,40 @@ extern "C" {
 #endif // _di_control_packet_receive_
 
 #ifndef _di_control_packet_process_
-  f_status_t control_packet_process(fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header) {
+  f_status_t control_packet_process(fll_program_data_t * const main, control_data_t * const data, control_payload_header_t * const header) {
+
+    f_string_static_t string_status = f_string_static_t_initialize;
+
+    {
+      const f_status_t status = f_status_string_to(header->status, &string_status);
+
+      if (F_status_is_error(status)) {
+        control_print_warning_packet_process_string_to_failed(main, header->status, status);
+      }
+    }
+
+    if (main->parameters.array[control_parameter_return_e].result == f_console_result_found_e) {
+      fll_print_format("%rresponse %q %q %q%r", main->output.to.stream, f_string_eol_s, control_payload_type_name(header->type), control_action_type_name(header->action), string_status, f_string_eol_s);
+    }
+    else if (header->type == control_payload_type_error_e) {
+      control_print_error_packet_response(main, data, *header, string_status);
+    }
+    else if (header->status == F_failure || header->status == F_busy || header->status == F_done || header->status == F_success) {
+      control_print_controller_packet_response(main, data, *header, string_status);
+    }
+    else {
 
-    if (header.type == control_payload_type_error_e) {
-      control_print_error_packet_response(main, data, header);
+      // Set type to 0 to inform the caller to handle this error.
+      header->type = 0;
 
-      return F_none;
+      return F_status_set_error(F_known_not);
     }
 
-    // @todo based on header->type, handle the data.
+    if (header->type == control_payload_type_error_e || header->status == F_failure || header->status == F_busy) {
+      return F_status_set_error(header->status);
+    }
 
-    return F_none;
+    return header->status;
   }
 #endif // _di_control_packet_process_
 
index 3ac9d5c46b1e2777f0aa5aada140b84f32f004ae..109f4055917c11c10300fd0a95fc990cf4a516eb 100644 (file)
@@ -32,19 +32,6 @@ extern "C" {
 #endif // _di_control_action_identify_
 
 /**
- * Get the name of the action type.
- *
- * @param type
- *   The action type id.
- *
- * @return
- *   The string associated with the action type.
- */
-#ifndef _di_control_action_type_name_
-  extern f_string_static_t control_action_type_name(const uint8_t type) F_attribute_visibility_internal_d;
-#endif // _di_control_action_type_name_
-
-/**
  * Verify that the additional parameters are reasonably correct for the identified action.
  *
  * @param main
@@ -130,9 +117,17 @@ extern "C" {
  *   The control data.
  * @param header
  *   The control payload packet header data.
+ *
+ * @return
+ *   F_done on success but action has no success or failure states.
+ *   F_success on success.
+ *
+ *   F_busy (with error bit)
+ *   F_failure (with error bit) on success but controller returned failure for action.
+ *   Any error (with error bit) on failure where the error is defined by the controller service.
  */
 #ifndef _di_control_packet_process_
-  extern f_status_t control_packet_process(fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header) F_attribute_visibility_internal_d;
+  extern f_status_t control_packet_process(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_process_
 
 /**
index 5a315037b6f55c2d00367fd56dfe77229eb2138c..476aa032f62ca4ee6e83cebba32f78882fb4172c 100644 (file)
@@ -7,6 +7,72 @@
 extern "C" {
 #endif
 
+#ifndef _di_control_print_controller_packet_response_
+  void control_print_controller_packet_response(fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header, const f_string_static_t string_status) {
+
+    if (header.status == F_failure) {
+      if (main->error.verbosity == f_console_verbosity_quiet_e) return;
+
+      flockfile(main->error.to.stream);
+
+      fl_print_format("%r%[%QThe action '%]", 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, control_action_type_name(header.action), main->context.set.notable);
+      fl_print_format("%[' failed with status '%]", main->error.to.stream, main->context.set.error, main->context.set.error);
+      fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, string_status, main->context.set.notable);
+      fl_print_format("%[' (%]", main->error.to.stream, main->context.set.error, main->context.set.error);
+      fl_print_format("%[%ui%]", main->error.to.stream, main->context.set.notable, header.status, main->context.set.notable);
+
+      if (header.length) {
+        fl_print_format("%[): %/Q%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, data->cache.large, data->cache.packet_contents.array[data->cache.packet_contents.used - 1].array[0], f_string_eol_s);
+      }
+      else {
+        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);
+
+      return;
+    }
+
+    if (header.status == F_busy) {
+      if (main->warning.verbosity == f_console_verbosity_quiet_e) return;
+
+      flockfile(main->warning.to.stream);
+
+      fl_print_format("%r%[%QThe action '%]", 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, control_action_type_name(header.action), main->context.set.notable);
+      fl_print_format("%[' could not be performed because the service is busy.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s);
+
+      funlockfile(main->warning.to.stream);
+
+      return;
+    }
+
+    if (main->output.verbosity == f_console_verbosity_quiet_e) return;
+
+    flockfile(main->output.to.stream);
+
+    fl_print_format("%rThe action '", main->output.to.stream, f_string_eol_s);
+    fl_print_format("%[%q%]", main->output.to.stream, main->context.set.notable, control_action_type_name(header.action), main->context.set.notable);
+
+    if (header.status == F_done) {
+      fl_print_format("' is performed", main->output.to.stream);
+    }
+    else {
+      fl_print_format("' is successfully performed", main->output.to.stream);
+    }
+
+    if (header.length) {
+      fl_print_format(": %/Q%r", main->output.to.stream, data->cache.large, data->cache.packet_contents.array[data->cache.packet_contents.used - 1].array[0], f_string_eol_s);
+    }
+    else {
+      fl_print_format(".%r", main->output.to.stream, f_string_eol_s);
+    }
+
+    funlockfile(main->output.to.stream);
+  }
+#endif // _di_control_print_controller_packet_response_
+
 #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 content_range) {
 
@@ -50,19 +116,21 @@ extern "C" {
 #endif // _di_control_print_debug_packet_message_
 
 #ifndef _di_control_print_error_packet_response_
-  void control_print_error_packet_response(fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header) {
+  void control_print_error_packet_response(fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header, const f_string_static_t string_status) {
 
     if (main->error.verbosity == f_console_verbosity_quiet_e) return;
 
     flockfile(main->error.to.stream);
 
     fl_print_format("%r%[%QReceived error response for " CONTROL_action_s " '%]", 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, control_action_type_name(header.action), main->context.set.notable);
-    fl_print_format("%[' (with status %[", 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, control_action_type_name(header.action), main->context.set.notable);
+    fl_print_format("%[' with status '%]", main->error.to.stream, main->context.set.error, main->context.set.error);
+    fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, string_status, main->context.set.notable);
+    fl_print_format("%[' (%]", main->error.to.stream, main->context.set.error, main->context.set.error);
     fl_print_format("%[%ui%]", main->error.to.stream, main->context.set.notable, header.status, main->context.set.notable);
 
     if (header.length) {
-      fl_print_format("%[): %/Q%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, data->cache.large, data->cache.header_contents.array[0].array[0], f_string_eol_s);
+      fl_print_format("%[): %/Q%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, data->cache.large, data->cache.packet_contents.array[data->cache.packet_contents.used - 1].array[0], f_string_eol_s);
     }
     else {
       fl_print_format("%[).%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s);
@@ -283,7 +351,7 @@ extern "C" {
 
     flockfile(main->warning.to.stream);
 
-    fl_print_format("%]%r%r%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s, f_string_eol_s, main->context.set.warning, main->context.set.warning);
+    fl_print_format("%]%r%r%[Received signal code%] ", main->warning.to.stream, main->context.set.reset, f_string_eol_s, f_string_eol_s, main->context.set.warning, main->context.set.warning);
     fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable);
     fl_print_format("%[.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s);
 
@@ -306,6 +374,23 @@ extern "C" {
   }
 #endif // _di_control_print_warning_packet_header_duplicate_object_
 
+#ifndef _di_control_print_warning_packet_process_string_to_failed_
+  void control_print_warning_packet_process_string_to_failed(fll_program_data_t * const main, const f_status_t status_of, const f_status_t status_error) {
+
+    if (main->warning.verbosity == f_console_verbosity_debug_e) return;
+
+    flockfile(main->warning.to.stream);
+
+    fl_print_format("%r%[%QFailed while calling f_status_string_to() for status%] ", main->output.to.stream, f_string_eol_s, main->context.set.warning, main->context.set.warning, main->context.set.warning);
+    fl_print_format("%[%ui%]", main->output.to.stream, main->context.set.notable, status_of, main->context.set.notable);
+    fl_print_format("%[, failing with status code%] ", main->output.to.stream, main->context.set.warning, status_error, main->context.set.warning);
+    fl_print_format("%[%ui%]", main->output.to.stream, main->context.set.notable, status_error, main->context.set.notable);
+    fl_print_format("%[.%]%r", main->output.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_process_string_to_failed_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 4c0cc1e0eef909097815765fba6d3e707ec02ec0..d0edb56201e287cbefe11713ebc13212368ce7f8 100644 (file)
@@ -13,6 +13,22 @@ extern "C" {
 #endif
 
 /**
+ * Print a message about a packet response.
+ *
+ * @param main
+ *   The main program data.
+ * @param data
+ *   The control data.
+ * @param header
+ *   The control payload packet header data.
+ * @param status
+ *   A string representing the name of the status code from header.status.
+ */
+#ifndef _di_control_print_controller_packet_response_
+  extern void control_print_controller_packet_response(fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header, const f_string_static_t string_status) F_attribute_visibility_internal_d;
+#endif // _di_control_print_controller_packet_response_
+
+/**
  * Print a message displaying the object and content for some packet header.
  *
  * @param main
@@ -61,9 +77,11 @@ extern "C" {
  *   The control data.
  * @param header
  *   The control payload packet header data.
+ * @param status
+ *   A string representing the name of the status code from header.status.
  */
 #ifndef _di_control_print_error_packet_response_
-  extern void control_print_error_packet_response(fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header) F_attribute_visibility_internal_d;
+  extern void control_print_error_packet_response(fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header, const f_string_static_t status) F_attribute_visibility_internal_d;
 #endif // _di_control_print_error_packet_response_
 /**
  * Print an error message about no actions being provided.
@@ -263,6 +281,22 @@ extern "C" {
   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_
 
+/**
+ * Print a warning message about a failure when calling f_status_string_to().
+ *
+ * @param main
+ *   The main program data.
+ * @param status_of
+ *   The status code to be translating to a string.
+ * @param status_error
+ *   The status code representing the failure status returned by f_status_string_to().
+ *
+ * @see f_status_string_to()
+ */
+#ifndef _di_control_print_warning_packet_process_string_to_failed_
+  extern void control_print_warning_packet_process_string_to_failed(fll_program_data_t * const main, const f_status_t status_of, const f_status_t status_error) F_attribute_visibility_internal_d;
+#endif // _di_control_print_warning_packet_process_string_to_failed_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
diff --git a/level_3/control/documents/packet_response.txt b/level_3/control/documents/packet_response.txt
new file mode 100644 (file)
index 0000000..d30d7ff
--- /dev/null
@@ -0,0 +1,47 @@
+# fss-0002
+
+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). 
+  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.
+
+  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\:
+    - status: Allowing only a single status header Object.
+    - type: Allowing only a single type header Object and may only be one of: "error" and "controller".
+    - 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".
+    - 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.
+  For any error responses that are associated with an action, then the action header is provided (otherwise it is not expected and is ignored).
+  For any error responses the Payload Content may be empty but when it is not, then the Payload Content is a single string representing a message further describing the error or the reason for the error.
+  These error responses represents errors in attempting to perform some action.
+  These responses are not used for actions that return an error as the result of a proper execution or performing of that action.
+
+  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_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.
+
+  When using the -R/--return parameter, the program prints specially formatted messages to help make the output more scriptable.
+
+  The form is "response [type] [action] [status]".
+  Examples\:
+    - A response that designates the action failed might look like: "response controller my_action F_failure".
+    - A response that designates the controller ran out of memory, preventing the action from being run: "response error my_action F_memory_not".
+    - A response that designates the controller ran successfully: "response controller my_action F_success".
+
+  When the control program fails to function due to some error, there will be no specially formatted message printed.
+  When the controller program fails before it can perform the requested action, then a "response error [action] [status]" formatted message is printed.
+  When the controller program successfully performs the action but the result of that action is an error, then a "response controller [action] F_failure" formatted message is printed.
index 03ab96429f45e194462541929e54faeb98399dbd..6cafcb72c86a0a9c30e2fb0dc2761a21b4821029 100644 (file)
@@ -2,7 +2,6 @@
 #
 # license: open-standard-license-1.0
 #
-#
 
 Featureless Settings Specification: 000f - Simple Packet:
   This is a network packet format that contains FSS-000E (Payload) within it.