]> Kevux Git Server - fll/commitdiff
Progress: Controller and Control sockets.
authorKevin Day <thekevinday@gmail.com>
Thu, 17 Mar 2022 03:56:05 +0000 (22:56 -0500)
committerKevin Day <thekevinday@gmail.com>
Thu, 17 Mar 2022 03:56:05 +0000 (22:56 -0500)
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

index bc1ae5368a63d83d43298faa6f12cf5940b7889d..36c55497332a089da5cf67232a25994c95e28b93 100644 (file)
@@ -224,8 +224,6 @@ extern "C" {
               else {
                 fll_error_print(main->error, F_status_set_fine(status), "control_packet_build", F_true);
               }
-
-              fll_print_dynamic_raw(f_string_eol_s, main->error.to.stream);
             }
           }
 
@@ -234,7 +232,6 @@ extern "C" {
 
             if (F_status_is_error(status)) {
               fll_error_print(main->error, F_status_set_fine(status), "control_packet_send", F_true);
-              fll_print_dynamic_raw(f_string_eol_s, main->error.to.stream);
             }
           }
 
@@ -250,8 +247,13 @@ extern "C" {
               else {
                 fll_error_print(main->error, F_status_set_fine(status), "control_packet_receive", F_true);
               }
+            }
+            else {
+              status = control_packet_process(main, &data, header);
 
-              fll_print_dynamic_raw(f_string_eol_s, main->error.to.stream);
+              if (F_status_is_error(status)) {
+                fll_error_print(main->error, F_status_set_fine(status), "control_packet_process", F_true);
+              }
             }
           }
 
index 533265f4f124774689b2db506b0a9875b990550d..4f441a52fb928385c9ba63b9b29be03e2cbb66f8 100644 (file)
@@ -62,6 +62,51 @@ 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) {
 
@@ -315,10 +360,24 @@ extern "C" {
       f_string_range_t range_packet = macro_f_string_range_t_initialize2(data->cache.large.used);
 
       status = fll_fss_basic_list_read(data->cache.large, state, &range_packet, &data->cache.packet_objects, &data->cache.packet_contents, &data->cache.delimits, 0, 0);
-      if (F_status_is_error(status)) return status;
+
+      if (F_status_is_error(status)) {
+        control_print_debug_packet_message(main, "Failure while reading FSS Basic List in the response packet", 0, 0, &status);
+
+        if (F_status_set_fine(status) == F_memory_not) {
+          return status;
+        }
+
+        return F_status_set_error(F_header);
+      }
 
       status = fl_fss_apply_delimit(data->cache.delimits, &data->cache.large);
-      if (F_status_is_error(status)) return status;
+
+      if (F_status_is_error(status)) {
+        control_print_debug_packet_message(main, "Failure while processing delimits for the FSS Basic List in the response packet", 0, 0, &status);
+
+        return F_status_set_error(F_header);
+      }
 
       data->cache.delimits.used = 0;
 
@@ -332,7 +391,9 @@ extern "C" {
 
             // 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);
+              control_print_debug_packet_message(main, "Multiple %[" F_fss_string_header_s "%] found in response packet", 0, 0, 0);
+
+              return F_status_set_error(F_payload_not);
             }
 
             content_header = &data->cache.packet_contents.array[i];
@@ -341,15 +402,31 @@ extern "C" {
 
             // Only a single "payload" is supported by the FSS-000E (Payload) standard.
             if (content_payload) {
-              return F_status_set_error(F_packet_not);
+              control_print_debug_packet_message(main, "Multiple %[" F_fss_string_payload_s "%] found in response packet", 0, 0, 0);
+
+              return F_status_set_error(F_payload_not);
+            }
+
+            if (i + 1 < data->cache.packet_contents.used) {
+              control_print_debug_packet_message(main, "Invalid FSS Payload format, the %[" F_fss_string_payload_s "%] is required to be the last FSS Basic List Object", 0, 0, 0);
+
+              return F_status_set_error(F_payload_not);
             }
 
             content_payload = &data->cache.packet_contents.array[i];
           }
         } // for
 
-        if (!content_header || !content_payload) {
-          return F_status_set_error(F_packet_not);
+        if (!content_header) {
+          control_print_debug_packet_message(main, "Did not find a %[" F_fss_string_header_s "%] in the response packet", 0, 0, 0);
+
+          return F_status_set_error(F_payload_not);
+        }
+
+        if (!content_payload) {
+          control_print_debug_packet_message(main, "Did not find a %[" F_fss_string_payload_s "%] in the response packet", 0, 0, 0);
+
+          return F_status_set_error(F_payload_not);
         }
 
         range_header = content_header->array[0];
@@ -362,21 +439,31 @@ extern "C" {
         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 = fll_fss_extended_read(data->cache.large, state, &range, &data->cache.header_objects, &data->cache.header_contents, 0, 0, &data->cache.delimits, 0);
+
+        if (F_status_is_error(status)) {
+          control_print_debug_packet_message(main, "Failure while reading FSS Extended in the response packet", 0, 0, &status);
+
+          if (F_status_set_fine(status) == F_memory_not) {
+            return status;
+          }
+
+          return F_status_set_error(F_header_not);
+        }
 
         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);
+        if (F_status_is_error(status)) {
+          control_print_debug_packet_message(main, "Failure while processing delimits for the FSS Basic List in the response packet", 0, 0, &status);
+
+          return F_status_set_error(F_header_not);
         }
 
-        // @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.
+        if (!data->cache.header_contents.used) {
+          control_print_debug_packet_message(main, "Did not find any Content within the %[" F_fss_string_header_s "%]", 0, 0, 0);
 
-        //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);
+          return F_status_set_error(F_header_not);
+        }
 
         for (i = 0; i < data->cache.header_objects.used; ++i) {
 
@@ -396,8 +483,9 @@ extern "C" {
               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);
+                control_print_debug_packet_message(main, "Failed to identify %[" CONTROL_action_s "%] from: ", &data->cache.large, &data->cache.header_contents.array[i].array[0], 0);
+
+                return F_status_set_error(F_header_not);
               }
             }
             else {
@@ -411,17 +499,18 @@ extern "C" {
 
               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);
+                control_print_debug_packet_message(main, "Failed to process number for %[" CONTROL_length_s "%] in the response packet, number is:", &data->cache.large, &data->cache.header_contents.array[i].array[0], &status);
+
+                return F_status_set_error(F_header_not);
               }
 
-              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);
+              if (number > F_type_size_max_32_unsigned_d) {
+                control_print_debug_packet_message(main, "Processed number for %[" CONTROL_length_s "%] exceeds allowed size in the response packet, number is:", &data->cache.large, &data->cache.header_contents.array[i].array[0], &status);
+
+                return F_status_set_error(F_header_not);
               }
 
               header->length = (uint16_t) number;
@@ -437,10 +526,12 @@ extern "C" {
 
               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.
+              // 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) {
+
+                // Not a number, so attempt get by status string name.
                 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);
@@ -451,13 +542,26 @@ extern "C" {
                 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;
+                  control_print_debug_packet_message(main, "Failed to process %[" CONTROL_status_s "%] in the response packet, Content is:", &data->cache.large, &data->cache.header_contents.array[i].array[0], &status);
+
+                  return F_status_set_error(F_header_not);
                 }
               }
               else if (F_status_is_error(status)) {
-                // @todo if debug print the reason for the failure.
-                return F_status_set_error(F_status);
+                control_print_debug_packet_message(main, "Failed to process number for %[" CONTROL_status_s "%] in the response packet, number is:", &data->cache.large, &data->cache.header_contents.array[i].array[0], &status);
+
+                if (F_status_set_fine(status) == F_memory_not) {
+                  return status;
+                }
+
+                return F_status_set_error(F_header_not);
+              }
+              else {
+                if (number > F_status_size_max_with_bits_d) {
+                  control_print_debug_packet_message(main, "Processed number for %[" CONTROL_status_s "%] exceeds allowed size in the response packet, number is:", &data->cache.large, &data->cache.header_contents.array[i].array[0], 0);
+
+                  return F_status_set_error(F_header_not);
+                }
               }
             }
             else {
@@ -477,8 +581,9 @@ extern "C" {
                 header->type = control_payload_type_error_e;
               }
               else {
-                // @todo if debug print the reason for the failure.
-                return F_status_set_error(F_header);
+                control_print_debug_packet_message(main, "Unknown %[" CONTROL_type_s "%] in response packet, Content is:", &data->cache.large, &data->cache.header_contents.array[i].array[0], 0);
+
+                return F_status_set_error(F_header_not);
               }
             }
             else {
@@ -487,16 +592,27 @@ extern "C" {
           }
         }
       }
-
-      // @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
     return F_none;
   }
 #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) {
+
+    if (header.type == control_payload_type_error_e) {
+      control_print_error_packet_response(main, data, header);
+
+      return F_none;
+    }
+
+    // @todo based on header->type, handle the data.
+
+    return F_none;
+  }
+#endif // _di_control_packet_process_
+
 #ifndef _di_control_packet_send_
   f_status_t control_packet_send(fll_program_data_t * const main, control_data_t * const data) {
 
index 89b7bf3e68e33d014367edc099b1059fa29e96bd..3ac9d5c46b1e2777f0aa5aada140b84f32f004ae 100644 (file)
@@ -32,6 +32,19 @@ 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
@@ -83,32 +96,46 @@ extern "C" {
  * @return
  *   F_none on success.
  *
- *   F_header (with error bit) If there is a problem processing the packet header.
+ *   F_header_not (with error bit) If there is a problem processing the packet header.
+ *   F_memory_not (with error bit) On out of memory issues (this is passed through from called functions).
  *   F_packet_not (with error bit) If the received packet is not a valid packet or not a supported packet structure.
+ *   F_payload_not (with error bit) If there is a problem processing the packet payload.
  *   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.
  *
  *   Errors (with error bit) from: f_socket_read().
- *   Errors (with error bit) from: f_string_dynamic_append().
  *   Errors (with error bit) from: f_string_dynamic_increase_by().
- *   Errors (with error bit) from: f_string_dynamic_resize().
- *   Errors (with error bit) from: fl_fss_apply_delimit().
- *   Errors (with error bit) from: fll_fss_basic_list_read().
+ *   Errors (with error bit) from: fl_conversion_dynamic_partial_to_number_unsigned().
  *   Errors (with error bit) from: fll_fss_extended_read().
+ *   Errors (with error bit) from: fll_fss_basic_list_read().
  *
  * @see f_socket_read()
- * @see f_string_dynamic_append()
  * @see f_string_dynamic_increase_by()
- * @see f_string_dynamic_resize()
+ * @see fl_conversion_dynamic_partial_to_number_unsigned()
  * @see fl_fss_apply_delimit()
- * @see fll_fss_basic_list_read()
  * @see fll_fss_extended_read()
+ * @see fll_fss_basic_list_read()
+ * @see fll_status_string_from()
  */
 #ifndef _di_control_packet_receive_
   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_
 
 /**
+ * Process the received and loaded packet.
+ *
+ * @param main
+ *   The main program data.
+ * @param data
+ *   The control data.
+ * @param header
+ *   The control payload packet header data.
+ */
+#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;
+#endif // _di_control_packet_process_
+
+/**
  * Send the payload to the remote socket, getting the payload from the large cache.
  *
  * @param main
index e218a7fe728e0d0aff6ba4d1546e93fbbbca77d2..5a315037b6f55c2d00367fd56dfe77229eb2138c 100644 (file)
@@ -1,5 +1,6 @@
 #include "control.h"
 #include "private-common.h"
+#include "private-control.h"
 #include "private-print.h"
 
 #ifdef __cplusplus
@@ -7,19 +8,70 @@ extern "C" {
 #endif
 
 #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) {
+  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) {
 
     if (main->output.verbosity == f_console_verbosity_debug_e) return;
 
-    flockfile(main->error.to.stream);
+    flockfile(main->output.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);
+    fl_print_format("' has value '%[%/Q%]'.%r", main->output.to.stream, main->context.set.notable, content, content_range, main->context.set.notable, f_string_eol_s);
 
-    funlockfile(main->error.to.stream);
+    funlockfile(main->output.to.stream);
   }
 #endif // _di_control_print_debug_packet_header_object_and_content_
 
+#ifndef _di_control_print_debug_packet_message_
+  void control_print_debug_packet_message(fll_program_data_t * const main, const f_string_t message, const f_string_static_t *buffer, const f_string_range_t *range, const f_status_t *status) {
+
+    if (main->output.verbosity == f_console_verbosity_debug_e) return;
+
+    flockfile(main->output.to.stream);
+
+    fl_print_format("%r%s", main->output.to.stream, f_string_eol_s, message, main->context.set.notable, main->context.set.notable);
+
+    if (buffer) {
+      if (range) {
+        fl_print_format("'%[%/Q%]'", main->output.to.stream, main->context.set.notable, *buffer, *range, main->context.set.notable);
+      }
+      else {
+        fl_print_format("'%[%/Q%]'", main->output.to.stream, main->context.set.notable, *buffer, main->context.set.notable);
+      }
+    }
+
+    if (status) {
+      fl_print_format(", with status code %[%ui%]'", main->output.to.stream, main->context.set.notable, *status, main->context.set.notable);
+    }
+
+    fl_print_format(".%r", main->output.to.stream, f_string_eol_s);
+
+    funlockfile(main->output.to.stream);
+  }
+#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) {
+
+    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("%[%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);
+    }
+    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);
+  }
+#endif // _di_control_print_error_packet_response_
+
 #ifndef _di_control_print_error_parameter_actions_none_
   void control_print_error_parameter_actions_none(fll_program_data_t * const main) {
 
@@ -163,7 +215,7 @@ extern "C" {
 
     if (main->error.verbosity == f_console_verbosity_quiet_e) return;
 
-    fll_print_format("%r%[%QThe received response is not a valid or supported packet.'%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
+    fll_print_format("%r%[%QThe received response is not a valid or supported packet.%]%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_response_packet_valid_not_
 
@@ -172,7 +224,7 @@ extern "C" {
 
     if (main->error.verbosity == f_console_verbosity_quiet_e) return;
 
-    fll_print_format("%r%[%QThe generated packet is too large, cannot send packet.'%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
+    fll_print_format("%r%[%QThe generated packet is too large, cannot send packet.%]%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_request_packet_too_large_
 
index 78396b825e401c6d144587d9a42d34e54ef5471d..4c0cc1e0eef909097815765fba6d3e707ec02ec0 100644 (file)
@@ -21,14 +21,51 @@ extern "C" {
  *   The object string.
  * @param content
  *   The content string.
- * @param range_content
+ * @param content_range
  *   The range representing the content where the content is found within the content string.
  */
 #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;
+  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 content_range) F_attribute_visibility_internal_d;
 #endif // _di_control_print_debug_packet_header_object_and_content_
 
 /**
+ * Print a debug message regarding some packet.
+ *
+ * @param main
+ *   The main program data.
+ * @param message
+ *   The message to print.
+ *
+ *   A single "%[" followed by a single "%]" is supported in the message and is replaced with "notable" context.
+ * @param buffer
+ *   (optional) An additonal message to print (this is syntax highlighted).
+ *   Set to NULL to not use.
+ * @param range
+ *   (optional) The range within the buffer to print rather than printing the entire buffer.
+ *   Set to NULL to not use.
+ *   This is ignored when buffer is NULL.
+ * @param status
+ *   (optional) A status code that triggered the failure (this is syntax highlighted).
+ *   Set to NULL to not use.
+ */
+#ifndef _di_control_print_debug_packet_message_
+  extern void control_print_debug_packet_message(fll_program_data_t * const main, const f_string_t message, const f_string_static_t *buffer, const f_string_range_t *range, const f_status_t *status) F_attribute_visibility_internal_d;
+#endif // _di_control_print_debug_packet_message_
+
+/**
+ * Print an error from the packet response.
+ *
+ * @param main
+ *   The main program data.
+ * @param data
+ *   The control data.
+ * @param header
+ *   The control payload packet header data.
+ */
+#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;
+#endif // _di_control_print_error_packet_response_
+/**
  * Print an error message about no actions being provided.
  *
  * @param main