]> Kevux Git Server - fll/commitdiff
Progress: Implement controller to/from control networking.
authorKevin Day <thekevinday@gmail.com>
Sun, 6 Mar 2022 22:56:52 +0000 (16:56 -0600)
committerKevin Day <thekevinday@gmail.com>
Sun, 6 Mar 2022 22:56:52 +0000 (16:56 -0600)
Continue implementing the contoller to control communication.

I thought I described the packet structures in addition to the payload structure.
It seems I have not.
This begins adding the packet structure documentation.

29 files changed:
level_0/f_console/c/console.h
level_0/f_fss/c/fss/common.h
level_3/control/c/control.c
level_3/control/c/private-common.c
level_3/control/c/private-common.h
level_3/control/c/private-control.c
level_3/control/c/private-control.h
level_3/controller/c/common/private-common.h
level_3/controller/c/common/private-control.h
level_3/controller/c/common/private-lock.c
level_3/controller/c/common/private-lock.h
level_3/controller/c/common/private-setting.c
level_3/controller/c/common/private-setting.h
level_3/controller/c/common/private-thread.h
level_3/controller/c/control/private-control.c
level_3/controller/c/control/private-control.h
level_3/controller/c/controller.c
level_3/controller/c/controller/private-controller.c
level_3/controller/c/controller/private-controller.h
level_3/controller/c/entry/private-entry.c
level_3/controller/c/lock/private-lock.c
level_3/controller/c/thread/private-thread.c
level_3/controller/c/thread/private-thread_control.c
level_3/controller/c/thread/private-thread_control.h
level_3/controller/c/thread/private-thread_entry.c
level_3/controller/c/thread/private-thread_process.c
level_3/controller/c/thread/private-thread_signal.c
level_3/controller/documents/packet.txt
level_3/controller/specifications/packet.txt

index bf2cb958d887c027e32cf0c5cedee2664885fdc3..f091d149f77ff7e78ad98bf0fcec11ebb673537a 100644 (file)
@@ -21,7 +21,7 @@
 #include <fll/level_0/string.h>
 #include <fll/level_0/utf.h>
 
-// fll-0 console includes
+// fll-0 console includes.
 #include <fll/level_0/console/common.h>
 
 #ifdef __cplusplus
index 76a2b685c3f298f0e38d1a9b239ec12e197d2b69..e8992ba5f213aa76e2b35ca2768aeae4e344af52 100644 (file)
@@ -78,6 +78,12 @@ extern "C" {
   #define f_fss_embedded_list_open_end_s  f_string_eol_s
   #define f_fss_embedded_list_close_s     f_fss_brace_close_s
   #define f_fss_embedded_list_close_end_s f_string_eol_s
+  #define f_fss_payload_header_open_s     f_fss_space_s
+  #define f_fss_payload_header_next_s     f_fss_space_s
+  #define f_fss_payload_header_close_s    f_string_eol_s
+  #define f_fss_payload_list_open_s       f_fss_colon_s
+  #define f_fss_payload_list_open_end_s   f_string_eol_s
+  #define f_fss_payload_list_close_s      f_string_eol_s
   #define f_fss_type_header_open_s        f_fss_pound_s
   #define f_fss_type_header_part1_s       f_fss_space_s
   #define f_fss_type_header_part2_s       f_fss_f_s
index 7e6c8dacc4cbf9968ad5e362cd7836d95f830d52..475b1c82c52b6f0418c61d8440f1b87856ed0f43 100644 (file)
@@ -208,13 +208,36 @@ extern "C" {
 
           data.socket.address = (struct sockaddr *) &socket_address;
           data.socket.domain = f_socket_domain_file_d;
-          data.socket.type = f_socket_type_datagram_d;
+          data.socket.type = f_socket_type_stream_d;
           data.socket.length = sizeof(struct sockaddr_un);
 
           status = control_settings_load(main, &data);
 
           if (F_status_is_error_not(status)) {
-            // @todo construct the packet, send the packet to the controller, and process the response.
+            status = control_payload_build(main, &data);
+
+            if (F_status_is_error(status)) {
+              fll_error_print(main->error, F_status_set_fine(status), "control_payload_build", F_true);
+              fll_print_dynamic_raw(f_string_eol_s, main->error.to.stream);
+            }
+          }
+
+          if (F_status_is_error_not(status)) {
+            status = control_payload_send(main, &data);
+
+            if (F_status_is_error(status)) {
+              fll_error_print(main->error, F_status_set_fine(status), "control_payload_send", F_true);
+              fll_print_dynamic_raw(f_string_eol_s, main->error.to.stream);
+            }
+          }
+
+          if (F_status_is_error_not(status)) {
+            status = control_payload_receive(main, &data);
+
+            if (F_status_is_error(status)) {
+              fll_error_print(main->error, F_status_set_fine(status), "control_payload_receive", F_true);
+              fll_print_dynamic_raw(f_string_eol_s, main->error.to.stream);
+            }
           }
 
           if (data.socket.id != -1) {
index 97ecf47d518cb66d81eb3a344b0c1692a004cffd..505b2130245c6654ab079b5470fef22bf82122f8 100644 (file)
@@ -16,12 +16,16 @@ extern "C" {
 #ifndef _di_control_strings_s_
   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(CONTROLLER_action_s, 0, CONTROLLER_action_s_length);
   const f_string_static_t control_command_s = macro_f_string_static_t_initialize(CONTROL_command_s, 0, CONTROL_command_s_length);
   const f_string_static_t control_default_s = macro_f_string_static_t_initialize(CONTROL_default_s, 0, CONTROL_default_s_length);
+  const f_string_static_t control_length_s = macro_f_string_static_t_initialize(CONTROLLER_length_s, 0, CONTROLLER_length_s_length);
   const f_string_static_t control_name_socket_s = macro_f_string_static_t_initialize(CONTROL_name_socket_s, 0, CONTROL_name_socket_s_length);
   const f_string_static_t control_path_socket_s = macro_f_string_static_t_initialize(CONTROL_path_socket_s, 0, CONTROL_path_socket_s_length);
   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);
+  const f_string_static_t control_status_s = macro_f_string_static_t_initialize(CONTROLLER_status_s, 0, CONTROLLER_status_s_length);
+  const f_string_static_t control_type_s = macro_f_string_static_t_initialize(CONTROLLER_type_s, 0, CONTROLLER_type_s_length);
 
   const f_string_static_t control_error_s = macro_f_string_static_t_initialize(CONTROL_error_s, 0, CONTROL_error_s_length);
   const f_string_static_t control_freeze_s = macro_f_string_static_t_initialize(CONTROL_freeze_s, 0, CONTROL_freeze_s_length);
@@ -41,8 +45,8 @@ extern "C" {
 #ifndef _di_control_data_delete_
   void control_data_delete(control_data_t * const data) {
 
-    f_string_dynamic_resize(0, &data->cache.buffer_large);
-    f_string_dynamic_resize(0, &data->cache.buffer_small);
+    f_string_dynamic_resize(0, &data->cache.large);
+    f_string_dynamic_resize(0, &data->cache.small);
   }
 #endif // _di_control_data_delete_
 
index 039994e44e5325a21d8fb7cb31245d0efb82924e..8888cc9cf1b97e31ae58b85372b42bf24398f4bb 100644 (file)
@@ -115,12 +115,16 @@ extern "C" {
     #define CONTROL_path_settings_s_length 21
   #endif // defined(_override_control_path_settings_) && defined(_override_control_path_settings_length_)
 
+  #define CONTROL_action_s             "action"
   #define CONTROL_command_s            "command"
   #define CONTROL_default_s            "default"
+  #define CONTROL_length_s             "length"
   #define CONTROL_name_socket_s        "name_socket"
   #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"
+  #define CONTROL_status_s             "status"
+  #define CONTROL_type_s               "type"
 
   #define CONTROL_error_s    "error"
   #define CONTROL_freeze_s   "freeze"
@@ -142,6 +146,10 @@ extern "C" {
   #define CONTROL_path_socket_s_length        11
   #define CONTROL_path_socket_prefix_s_length 18
   #define CONTROL_path_socket_suffix_s_length 18
+  #define CONTROL_type_s_length               4
+  #define CONTROL_status_s_length             6
+  #define CONTROL_length_s_length             6
+  #define CONTROL_action_s_length             6
 
   #define CONTROL_error_s_length    5
   #define CONTROL_freeze_s_length   6
@@ -159,12 +167,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_command_s;
   extern const f_string_static_t control_default_s;
+  extern const f_string_static_t control_length_s;
   extern const f_string_static_t control_name_socket_s;
   extern const f_string_static_t control_path_socket_s;
   extern const f_string_static_t control_path_socket_prefix_s;
   extern const f_string_static_t control_path_socket_suffix_s;
+  extern const f_string_static_t control_status_s;
+  extern const f_string_static_t control_type_s;
 
   extern const f_string_static_t control_error_s;
   extern const f_string_static_t control_freeze_s;
@@ -217,13 +229,13 @@ extern "C" {
 /**
  * The control cache.
  *
- * buffer_large: A buffer for storing large sets of data.
- * buffer_small: A buffer for storing small sets of data.
+ * large: A buffer for storing large sets of data.
+ * small: A buffer for storing small sets of data.
  */
 #ifndef _di_control_cache_t_
   typedef struct {
-    f_string_dynamic_t buffer_large;
-    f_string_dynamic_t buffer_small;
+    f_string_dynamic_t large;
+    f_string_dynamic_t small;
   } control_cache_t;
 
   #define control_cache_initialize \
@@ -257,6 +269,7 @@ extern "C" {
       0, \
       f_string_dynamic_t_initialize, \
       f_socket_t_initialize, \
+      /*f_string_dynamic_t_initialize,*/ \
       0, \
     }
 #endif // _di_control_data_t_
index 5b6f8d6f29c3805773f070d648ed2f083e96fead..96ff167ffc47ce0745b94f8780a85aabb178a62d 100644 (file)
@@ -133,8 +133,9 @@ extern "C" {
         return F_none;
     }
 
+    // @todo the reboot and shutdown need to support date and time commands: "now", "in (a time)", and "at (a time)".
     if (data->command == control_command_type_reboot_e) {
-      // @todo
+      // @todo (also needs to support kexec calls or kexec needs its own command, which will likely be in the controller program.)
     }
 
     if (data->command == control_command_type_shutdown_e) {
@@ -145,20 +146,123 @@ extern "C" {
   }
 #endif // _di_control_command_verify_
 
+#ifndef _di_control_payload_build_
+  f_status_t control_payload_build(fll_program_data_t * const main, control_data_t * const data) {
+
+    data->cache.large.used = 0;
+    data->cache.small.used = 0;
+
+    f_array_length_t i = 0;
+    f_array_length_t length = 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;
+
+    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
+
+    status = f_string_dynamic_resize(length + 11, &data->cache.large);
+    if (F_status_is_error(status)) return status;
+
+    // @todo append the string bit and the length bits.
+
+    // The "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_sa, &data->cache.large);
+    if (F_status_is_error(status)) return status;
+
+    // The "type ..." line.
+    status = f_string_dynamic_append(control_type_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[0]], &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 "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;
+    } // for
+
+    // The "length 0" line.
+    status = f_string_dynamic_append(control_length_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(f_string_ascii_0_s, &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;
+
+    // The "payload:" line.
+    status = f_string_dynamic_append(f_fss_string_payload_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_sa, &data->cache.large);
+    if (F_status_is_error(status)) return status;
+
+    return F_none;
+  }
+#endif // _di_control_payload_build_
+
+#ifndef _di_control_payload_receive_
+  f_status_t control_payload_receive(fll_program_data_t * const main, control_data_t * const data) {
+
+    // @todo
+    return F_none;
+  }
+#endif // _di_control_payload_receive_
+
+#ifndef _di_control_payload_send_
+  f_status_t control_payload_send(fll_program_data_t * const main, control_data_t * const data) {
+
+    // @todo
+    return F_none;
+  }
+#endif // _di_control_payload_send_
+
 #ifndef _di_control_settings_load_
   f_status_t control_settings_load(fll_program_data_t * const main, control_data_t * const data) {
 
     f_status_t status = F_none;
 
-    data->cache.buffer_small.used = 0;
+    data->cache.small.used = 0;
 
     if (main->parameters.array[control_parameter_settings_e].result == f_console_result_additional_e) {
       const f_array_length_t index = main->parameters.array[control_parameter_settings_e].values.array[main->parameters.array[control_parameter_settings_e].values.used - 1];
 
-      status = f_string_dynamic_append(data->argv[index], &data->cache.buffer_small);
+      status = f_string_dynamic_append(data->argv[index], &data->cache.small);
     }
     else {
-      status = f_string_dynamic_append(control_path_settings_s, &data->cache.buffer_small);
+      status = f_string_dynamic_append(control_path_settings_s, &data->cache.small);
     }
 
     if (F_status_is_error(status)) {
@@ -170,20 +274,20 @@ extern "C" {
     {
       f_file_t file = f_file_t_initialize;
 
-      status = f_file_stream_open(data->cache.buffer_small, f_file_open_mode_read_s, &file);
+      status = f_file_stream_open(data->cache.small, f_file_open_mode_read_s, &file);
 
       if (F_status_is_error(status)) {
-        fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_open", F_true, data->cache.buffer_small, f_file_operation_open_s, fll_error_file_type_file_e);
+        fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_open", F_true, data->cache.small, f_file_operation_open_s, fll_error_file_type_file_e);
 
         return status;
       }
 
-      status = f_file_stream_read(file, &data->cache.buffer_large);
+      status = f_file_stream_read(file, &data->cache.large);
 
       f_file_stream_close(F_true, &file);
 
       if (F_status_is_error(status)) {
-        fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_read", F_true, data->cache.buffer_small, f_file_operation_read_s, fll_error_file_type_file_e);
+        fll_error_file_print(main->error, F_status_set_fine(status), "f_file_stream_read", F_true, data->cache.small, f_file_operation_read_s, fll_error_file_type_file_e);
 
         return status;
       }
@@ -195,16 +299,16 @@ extern "C" {
     f_fss_contents_t contents = f_fss_contents_t_initialize;
     f_fss_delimits_t delimits = f_fss_delimits_t_initialize;
 
-    status = fll_fss_extended_read(data->cache.buffer_large, state, &range, &objects, &contents, 0, 0, &delimits, 0);
+    status = fll_fss_extended_read(data->cache.large, state, &range, &objects, &contents, 0, 0, &delimits, 0);
 
     if (F_status_is_error(status)) {
-      fll_error_file_print(main->error, F_status_set_fine(status), "fll_fss_extended_read", F_true, data->cache.buffer_small, f_file_operation_process_s, fll_error_file_type_file_e);
+      fll_error_file_print(main->error, F_status_set_fine(status), "fll_fss_extended_read", F_true, data->cache.small, f_file_operation_process_s, fll_error_file_type_file_e);
     }
     else {
-      status = fl_fss_apply_delimit(delimits, &data->cache.buffer_large);
+      status = fl_fss_apply_delimit(delimits, &data->cache.large);
 
       if (F_status_is_error(status)) {
-        fll_error_file_print(main->error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true, data->cache.buffer_small, f_file_operation_process_s, fll_error_file_type_file_e);
+        fll_error_file_print(main->error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true, data->cache.small, f_file_operation_process_s, fll_error_file_type_file_e);
       }
     }
 
@@ -231,7 +335,7 @@ extern "C" {
 
             range.stop = parameter_names[j].used - 1;
 
-            if (fl_string_dynamic_partial_compare(parameter_names[j], data->cache.buffer_large, range, objects.array[i]) == F_equal_to) {
+            if (fl_string_dynamic_partial_compare(parameter_names[j], data->cache.large, range, objects.array[i]) == F_equal_to) {
               parameter_hass[j] = F_true;
               parameter_ats[j] = i;
 
@@ -241,18 +345,18 @@ extern "C" {
         } // for
       }
 
-      data->cache.buffer_small.used = 0;
+      data->cache.small.used = 0;
 
       if (main->parameters.array[control_parameter_socket_e].result == f_console_result_additional_e) {
         const f_array_length_t index = main->parameters.array[control_parameter_socket_e].values.array[main->parameters.array[control_parameter_socket_e].values.used - 1];
 
-        status = f_string_dynamic_append(data->argv[index], &data->cache.buffer_small);
+        status = f_string_dynamic_append(data->argv[index], &data->cache.small);
       }
       else if (parameter_hass[1]) {
-        status = f_string_dynamic_partial_append_nulless(data->cache.buffer_large, objects.array[parameter_ats[1]], &data->cache.buffer_small);
+        status = f_string_dynamic_partial_append_nulless(data->cache.large, objects.array[parameter_ats[1]], &data->cache.small);
       }
       else {
-        status = f_string_dynamic_append(controller_path_socket_s, &data->cache.buffer_small);
+        status = f_string_dynamic_append(controller_path_socket_s, &data->cache.small);
       }
 
       if (F_status_is_error(status)) {
@@ -264,25 +368,25 @@ extern "C" {
         }
       }
 
-      status = f_file_exists(data->cache.buffer_small);
+      status = f_file_exists(data->cache.small);
 
       if (F_status_is_error(status) || status == F_false) {
         if (F_status_is_error(status)) {
-          fll_error_file_print(main->error, F_status_set_fine(status), "f_file_exists", F_true, data->cache.buffer_small, f_file_operation_find_s, fll_error_file_type_directory_e);
+          fll_error_file_print(main->error, F_status_set_fine(status), "f_file_exists", F_true, data->cache.small, f_file_operation_find_s, fll_error_file_type_directory_e);
 
           if (main->error.verbosity != f_console_verbosity_quiet_e) {
             fll_print_dynamic_raw(f_string_eol_s, main->error.to.stream);
           }
         }
 
-        control_print_error_socket_file_missing(main, data->cache.buffer_small);
+        control_print_error_socket_file_missing(main, data->cache.small);
 
         status = F_status_set_error(F_socket_not);
       }
 
       // Construct the file name when the socket path is a directory.
-      else if (f_file_is(data->cache.buffer_small, F_file_type_directory_d, F_true) == F_true) {
-        status = f_string_dynamic_append_assure(f_path_separator_s, &data->cache.buffer_small);
+      else if (f_file_is(data->cache.small, F_file_type_directory_d, F_true) == F_true) {
+        status = f_string_dynamic_append_assure(f_path_separator_s, &data->cache.small);
 
         if (F_status_is_error(status)) {
           fll_error_print(main->error, F_status_set_fine(status), "f_string_dynamic_append_assure", F_true);
@@ -311,13 +415,13 @@ extern "C" {
             if (append_ids[i] && main->parameters.array[append_ids[i]].result == f_console_result_additional_e) {
               const f_array_length_t index = main->parameters.array[append_ids[i]].values.array[main->parameters.array[append_ids[i]].values.used - 1];
 
-              status = f_string_dynamic_append(data->argv[index], &data->cache.buffer_small);
+              status = f_string_dynamic_append(data->argv[index], &data->cache.small);
             }
             else if (append_hass[i]) {
-              status = f_string_dynamic_partial_append_nulless(data->cache.buffer_large, objects.array[append_hass[i]], &data->cache.buffer_small);
+              status = f_string_dynamic_partial_append_nulless(data->cache.large, objects.array[append_hass[i]], &data->cache.small);
             }
             else {
-              status = f_string_dynamic_append_nulless(append_defaults[i], &data->cache.buffer_small);
+              status = f_string_dynamic_append_nulless(append_defaults[i], &data->cache.small);
             }
 
             if (F_status_is_error(status)) {
@@ -333,26 +437,26 @@ extern "C" {
           } // for
 
           if (F_status_is_error_not(status)) {
-            status = f_file_exists(data->cache.buffer_small);
+            status = f_file_exists(data->cache.small);
 
             if (F_status_is_error(status) || status == F_false) {
               if (F_status_is_error(status)) {
-                fll_error_file_print(main->error, F_status_set_fine(status), "f_file_exists", F_true, data->cache.buffer_small, f_file_operation_find_s, fll_error_file_type_directory_e);
+                fll_error_file_print(main->error, F_status_set_fine(status), "f_file_exists", F_true, data->cache.small, f_file_operation_find_s, fll_error_file_type_directory_e);
 
                 if (main->error.verbosity != f_console_verbosity_quiet_e) {
                   fll_print_dynamic_raw(f_string_eol_s, main->error.to.stream);
                 }
               }
 
-              control_print_error_socket_file_missing(main, data->cache.buffer_small);
+              control_print_error_socket_file_missing(main, data->cache.small);
 
               status = F_status_set_error(F_socket_not);
             }
           }
 
           if (F_status_is_error_not(status)) {
-            if (f_file_is(data->cache.buffer_small, F_file_type_socket_d, F_true) == F_false) {
-              control_print_error_socket_file_not(main, data->cache.buffer_small);
+            if (f_file_is(data->cache.small, F_file_type_socket_d, F_true) == F_false) {
+              control_print_error_socket_file_not(main, data->cache.small);
 
               status = F_status_set_error(F_socket_not);
             }
@@ -368,7 +472,7 @@ extern "C" {
                 fll_print_dynamic_raw(f_string_eol_s, main->error.to.stream);
               }
 
-              control_print_error_socket_file_failed(main, data->cache.buffer_small);
+              control_print_error_socket_file_failed(main, data->cache.small);
             }
           }
 
@@ -382,7 +486,7 @@ extern "C" {
                 fll_print_dynamic_raw(f_string_eol_s, main->error.to.stream);
               }
 
-              control_print_error_socket_file_failed(main, data->cache.buffer_small);
+              control_print_error_socket_file_failed(main, data->cache.small);
             }
           }
         }
@@ -393,17 +497,17 @@ extern "C" {
     f_string_rangess_resize(0, &contents);
     f_array_lengths_resize(0, &delimits);
 
-    data->cache.buffer_large.used = 0;
-    data->cache.buffer_small.used = 0;
+    data->cache.large.used = 0;
+    data->cache.small.used = 0;
 
     if (F_status_is_error_not(status)) {
-      if (data->cache.buffer_large.size > control_default_buffer_limit_soft_large_d) {
-        status = f_string_dynamic_resize(control_default_buffer_limit_soft_large_d, &data->cache.buffer_large);
+      if (data->cache.large.size > control_default_buffer_limit_soft_large_d) {
+        status = f_string_dynamic_resize(control_default_buffer_limit_soft_large_d, &data->cache.large);
       }
 
       if (F_status_is_error_not(status)) {
-        if (data->cache.buffer_small.size > control_default_buffer_limit_soft_small_d) {
-          status = f_string_dynamic_resize(control_default_buffer_limit_soft_small_d, &data->cache.buffer_small);
+        if (data->cache.small.size > control_default_buffer_limit_soft_small_d) {
+          status = f_string_dynamic_resize(control_default_buffer_limit_soft_small_d, &data->cache.small);
         }
       }
     }
index cbcb94ea7746ccdc0222ac9bf1655143be9ea1b5..0ee4988c0af6727b5b51db30ffa6ebe5d94d751e 100644 (file)
@@ -42,6 +42,42 @@ extern "C" {
 #ifndef _di_control_command_verify_
   extern f_status_t control_command_verify(fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d;
 #endif // _di_control_command_verify_
+
+/**
+ * Build the payload, storing it in the large cache.
+ *
+ * @param main
+ *   The main program data.
+ * @param data
+ *   The control data.
+ */
+#ifndef _di_control_payload_build_
+  extern f_status_t control_payload_build(fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d;
+#endif // _di_control_payload_build_
+
+/**
+ * Receive the response from the remote socket, storing it in the large cache.
+ *
+ * @param main
+ *   The main program data.
+ * @param data
+ *   The control data.
+ */
+#ifndef _di_control_payload_receive_
+  extern f_status_t control_payload_receive(fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d;
+#endif // _di_control_payload_receive_
+
+/**
+ * Send the payload to the remote socket, getting the payload from the large cache.
+ *
+ * @param main
+ *   The main program data.
+ * @param data
+ *   The control data.
+ */
+#ifndef _di_control_payload_send_
+  extern f_status_t control_payload_send(fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d;
+#endif // _di_control_payload_send_
 /**
  * Load and process the control settings file.
  *
index 019ad32503b1b3777a49d8ddf518ef808510a832..6318fc33eaaf961e2750347ef6a998632c8a0627 100644 (file)
@@ -20,10 +20,10 @@ extern "C" {
 #include "private-task.h"
 #include "private-process.h"
 #include "private-entry.h"
+#include "private-control.h"
 #include "private-setting.h"
 #include "private-thread.h"
 #include "private-state.h"
-#include "private-control.h"
 
 /**
  * All special strings used within this program.
index 009b8fa5cbaf4fc38582985ec9750e340e066f0a..e0834983660c2eb853ea5095d15d6170ef72da23 100644 (file)
@@ -19,7 +19,7 @@ extern "C" {
  *   - socket_backlog:     The amount of waiting client connections to support while handling a socket connection.
  *   - socket_buffer:      The preferred max size of the buffer such that if the buffer exceeds this then it is reallocated to this size at the end of processing.
  *   - socket_buffer_max:  The max size allowed in the buffer (this value must not be set smaller than the packet headers).
- *   - socket_cache:       The preferred max size of the contol cache such that if the cache exceeds this then it is reallocated to this size at the end of processing.
+ *   - socket_cache:       The preferred max size of the control cache such that if the cache exceeds this then it is reallocated to this size at the end of processing.
  *   - socket_header:      The minimum size in bytes of the packet header to read to be able to process the size information.
  *   - socket_linger:      The number of seconds to linger the connection before closing.
  *   - socket_timeout:     The number of microseconds to wait.
@@ -36,20 +36,46 @@ extern "C" {
   #define controller_control_default_socket_payload_max_d 4294965248
 #endif // _di_controller_defaults_
 
+
 /**
- * A structure for control processing.
+ * The control data.
+ *
+ * controller_control_flag_*:
+ *   - readonly:  Control is set to read-only mode.
+ *   - has_user:  A user is manually specified.
+ *   - has_group: A group is manually specified.
+ *   - has_mode:  A file mode is manually specified.
  *
+ * flag:    Flags from controller_control_flag_*.
+ * user:    The user ID, if specified.
+ * group:   The group ID, if specified.
+ * mode:    The file mode, if specified.
  * server:  The server socket connection.
  * client:  The client socket connection.
  * cache_1: A generic buffer used for caching control related data.
  * cache_2: A generic buffer used for caching control related data.
+ * cache_3: A generic buffer used for caching control related data.
  * input:   A buffer used for receiving data from the client.
  * output:  A buffer used for transmitting data to the client.
+ * address: The socket address structure.
  */
 #ifndef _di_controller_control_t_
+  enum {
+    controller_control_flag_readonly_e  = 0x1,
+    controller_control_flag_has_user_e  = 0x2,
+    controller_control_flag_has_group_e = 0x4,
+    controller_control_flag_has_mode_e  = 0x8,
+  };
+
   typedef struct {
-    f_socket_t *server;
-    f_socket_t *client;
+    uint8_t flag;
+
+    uid_t user;
+    gid_t group;
+    mode_t mode;
+
+    f_socket_t server;
+    f_socket_t client;
 
     f_string_dynamic_t cache_1;
     f_string_dynamic_t cache_2;
@@ -57,26 +83,23 @@ extern "C" {
 
     f_string_dynamic_t input;
     f_string_dynamic_t output;
+
+    struct sockaddr_un address;
   } controller_control_t;
 
   #define controller_control_t_initialize { \
     0, \
+    -1, \
+    -1, \
     0, \
+    f_socket_t_initialize, \
+    f_socket_t_initialize, \
     f_string_dynamic_t_initialize, \
     f_string_dynamic_t_initialize, \
     f_string_dynamic_t_initialize, \
     f_string_dynamic_t_initialize, \
     f_string_dynamic_t_initialize, \
-  }
-
-  #define macro_controller_control_t_initialize(server, client) { \
-    0, \
-    0, \
-    f_string_dynamic_t_initialize, \
-    f_string_dynamic_t_initialize, \
-    f_string_dynamic_t_initialize, \
-    f_string_dynamic_t_initialize, \
-    f_string_dynamic_t_initialize, \
+    { }, \
   }
 #endif // _di_controller_control_t_
 
index 050b94a727d8176ec30bc213146cd3a99c7466c5..84cc6854f9e634c467c891951987b67308565f0e 100644 (file)
@@ -44,8 +44,8 @@ extern "C" {
 #ifndef _di_controller_lock_delete_simple_
   void controller_lock_delete_simple(controller_lock_t * const lock) {
 
-    controller_lock_delete_mutex(&lock->print);
     controller_lock_delete_mutex(&lock->alert);
+    controller_lock_delete_mutex(&lock->print);
 
     controller_lock_delete_rw(&lock->process);
     controller_lock_delete_rw(&lock->rule);
index 98af3d612ee32da3cc87c303a537e418f7c6173a..3132d3af22ddf7f958a84bf49ec21ed9b22156a0 100644 (file)
@@ -51,7 +51,7 @@ extern "C" {
  *
  * @param mutex
  *   The mutex lock to delete.
- *   Will be set to NULLif delete succeeded.
+ *   Will be set to NULL if delete succeeded.
  */
 #ifndef _di_controller_lock_delete_mutex_
   extern void controller_lock_delete_mutex(f_thread_mutex_t *mutex) F_attribute_visibility_internal_d;
index 2ffb1e24bc95fa420445a85234bcc6fc540f5275..71723de662f66248675285ab741db664b085284d 100644 (file)
@@ -8,13 +8,15 @@ extern "C" {
 #ifndef _di_controller_setting_delete_simple_
   void controller_setting_delete_simple(controller_setting_t * const setting) {
 
-    f_string_dynamic_resize(0, &setting->path_control);
+    f_string_dynamic_resize(0, &setting->name_entry);
+
     f_string_dynamic_resize(0, &setting->path_cgroup);
+    f_string_dynamic_resize(0, &setting->path_control);
     f_string_dynamic_resize(0, &setting->path_current);
     f_string_dynamic_resize(0, &setting->path_pid);
     f_string_dynamic_resize(0, &setting->path_setting);
 
-    f_string_dynamic_resize(0, &setting->name_entry);
+    controller_control_delete_simple(&setting->control);
 
     controller_entry_items_delete_simple(&setting->entry.items);
     controller_entry_items_delete_simple(&setting->exit.items);
index e62f27797688687cbaf9c37744d68ea3cdb9fcb6..72dd25cd223fc2a065583a42613997c5121dceb6 100644 (file)
@@ -27,25 +27,24 @@ extern "C" {
  *   - program: Run as a program, exiting when finished prrocess entry (and any respective exit).
  *   - service: Run as a service, listening for requests after processing entry.
  *
- * interruptible:      TRUE if the program responds to interrupt signals, FALSE to block/ignore interrupt signals.
- * pid_created:        TRUE if the PID file has been created.
- * ready:              State representing if the settings are all loaded and is ready to run program operations.
- * mode:               Controller setting mode based on the setting mode enumerator.
- * control_group:      Group role of the control socket.
- * control_moode:      Mode role of the control socket.
- * control_readonly:   TRUE if the control is set to readonly, FALSE otherwise.
- * control_socket:     The control socket data.
- * control_user:       User role of the control socket.
- * failsafe_enabled:   TRUE if failsafe execution is enabled, FALSE otherwise.
- * failsafe_item_id:   The Entry Item ID to execute when failsafe execution is enabled.
- * path_cgroup:        Directory path to the cgroup directory.
- * path_control:       File path to the control socket.
- * path_pid:           File path to the PID file.
- * path_setting:       File path to the setting directory.
- * entry:              The Entry settings.
- * rules:              All rules and their respective settings.
+ * controller_setting_flag_*:
+ *   - interruptible: When specified, program responds to interrupt signals, otherwise block/ignore interrupt signals.
+ *   - pid_created:   When specified, the program responds to interrupt signals, otherwise block/ignore interrupt signals.
+ *   - failsafe:      When specified, failsafe mode is enabled, otherwise failsafe mode is disabled.
+ *
+ * flag:             Flags from controller_setting_flag_*.
+ * ready:            State representing if the settings are all loaded and is ready to run program operations.
+ * mode:             Controller setting mode based on the setting mode enumerator.
+ * control:          The control socket data.
+ * failsafe_item_id: The Entry Item ID to execute when failsafe execution is enabled.
+ * path_cgroup:      Directory path to the cgroup directory.
+ * path_control:     File path to the control socket (used for printing the path).
+ * path_pid:         File path to the PID file.
+ * path_setting:     File path to the setting directory.
+ * entry:            The Entry settings.
+ * rules:            All rules and their respective settings.
  */
-#ifndef _di_controller_setting_t
+#ifndef _di_controller_setting_t_
   enum {
     controller_setting_ready_no_e = 0,
     controller_setting_ready_wait_e,
@@ -60,21 +59,21 @@ extern "C" {
     controller_setting_mode_program_e,
   };
 
+  enum {
+    controller_setting_flag_interruptible_e = 0x1,
+    controller_setting_flag_pid_created_e   = 0x2,
+    controller_setting_flag_failsafe_e      = 0x4,
+  };
+
   typedef struct {
-    bool interruptible;
-    bool pid_created;
+    uint8_t flag;
     uint8_t ready;
     uint8_t mode;
 
-    gid_t control_group;
-    mode_t control_mode;
-    bool control_readonly;
-    f_socket_t control_socket;
-    uid_t control_user;
-
-    bool failsafe_enabled;
     f_array_length_t failsafe_item_id;
 
+    controller_control_t control;
+
     f_string_dynamic_t path_cgroup;
     f_string_dynamic_t path_control;
     f_string_dynamic_t path_current;
@@ -89,17 +88,11 @@ extern "C" {
   } controller_setting_t;
 
   #define controller_setting_t_initialize { \
-    F_false, \
-    F_false, \
-    0, \
-    0, \
     0, \
     0, \
-    F_false, \
-    f_socket_t_initialize, \
     0, \
-    F_false, \
     0, \
+    controller_control_t_initialize, \
     f_string_dynamic_t_initialize, \
     f_string_dynamic_t_initialize, \
     f_string_dynamic_t_initialize, \
@@ -110,7 +103,7 @@ extern "C" {
     controller_entry_t_initialize, \
     controller_rules_t_initialize, \
   }
-#endif // _di_controller_setting_t
+#endif // _di_controller_setting_t_
 
 /**
  * Fully deallocate all memory for the given setting without caring about return status.
index 68da8693503ed251c4a6f82ed2ae2cd777550b46..01af260ef1c4b4f0185da1aa975a95a8ea7c1c73 100644 (file)
@@ -25,7 +25,6 @@ extern "C" {
  * id_cleanup: The thread ID representing the Cleanup Process.
  * id_control: The thread ID representing the Control Process.
  * id_entry:   The thread ID representing the Entry or Exit Process.
- * id_listen:  The thread ID representing the Control Process Listener.
  * id_rule:    The thread ID representing the Rule Process.
  * id_signal:  The thread ID representing the Signal Process.
  * lock:       A r/w lock for operating on this structure.
@@ -106,7 +105,6 @@ extern "C" {
     f_thread_id_t id_cleanup;
     f_thread_id_t id_control;
     f_thread_id_t id_entry;
-    f_thread_id_t id_listen;
     f_thread_id_t id_rule;
     f_thread_id_t id_signal;
 
@@ -124,7 +122,6 @@ extern "C" {
     f_thread_id_t_initialize, \
     f_thread_id_t_initialize, \
     f_thread_id_t_initialize, \
-    f_thread_id_t_initialize, \
     controller_lock_t_initialize, \
     controller_processs_t_initialize, \
     controller_cache_t_initialize, \
index dee5356a7f6cfbcdd2ae8f92c1775162faaa38a0..080d6140da00f7e38ba9f988879219558519e960 100644 (file)
@@ -10,21 +10,23 @@ extern "C" {
 #ifndef _di_controller_control_accept_
   f_status_t controller_control_accept(const controller_global_t * const global, controller_control_t * const control) {
 
-    f_socket_t client = f_socket_t_initialize;
+    /*if (control->client.id != -1) {
+      f_socket_disconnect(&control->client, f_socket_close_fast_e);
 
-    control->client = &client;
+      control->client.id = -1;
+    }*/
 
-    f_status_t status = f_socket_accept(&client, control->server->id);
+    f_status_t status = f_socket_accept(&control->client, control->server.id);
 
     if (F_status_is_error(status)) {
-      f_socket_disconnect(&client, f_socket_close_fast_e);
+      f_socket_disconnect(&control->client, f_socket_close_fast_e);
 
       controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_socket_accept", F_true);
 
       return status;
     }
 
-    controller_control_configure_client(global, &client);
+    controller_control_configure_client(global, &control->client);
 
     control->input.used = 0;
     control->output.used = 0;
@@ -35,11 +37,11 @@ extern "C" {
     memset(buffer, 0, controller_control_default_socket_buffer_d + 1);
 
     // Pre-process the packet header.
-    client.size_read = controller_control_default_socket_header_d;
-    status = f_socket_read(&client, f_socket_flag_peek_d, buffer, &length);
+    control->client.size_read = controller_control_default_socket_header_d;
+    status = f_socket_read(&control->client, f_socket_flag_peek_d, buffer, &length);
 
     if (F_status_is_error(status)) {
-      f_socket_disconnect(&client, f_socket_close_fast_e);
+      f_socket_disconnect(&control->client, f_socket_close_fast_e);
 
       controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_socket_read", F_true);
 
@@ -49,7 +51,7 @@ extern "C" {
     if (!length) {
       status = controller_control_respond_error_string(global, control, F_empty, "Received packet is empty.");
 
-      f_socket_disconnect(&client, f_socket_close_fast_e);
+      f_socket_disconnect(&control->client, f_socket_close_fast_e);
 
       if (F_status_is_error(status)) return status;
 
@@ -59,7 +61,7 @@ extern "C" {
     if (length < controller_control_default_socket_header_d) {
       status = controller_control_respond_error_string(global, control, F_too_large, "Received packet is too small.");
 
-      f_socket_disconnect(&client, f_socket_close_fast_e);
+      f_socket_disconnect(&control->client, f_socket_close_fast_e);
 
       if (F_status_is_error(status)) return status;
 
@@ -69,7 +71,7 @@ extern "C" {
     if (length > controller_control_default_socket_buffer_max_d) {
       status = controller_control_respond_error_string(global, control, F_too_large, "Received packet is too large.");
 
-      f_socket_disconnect(&client, f_socket_close_fast_e);
+      f_socket_disconnect(&control->client, f_socket_close_fast_e);
 
       if (F_status_is_error(status)) return status;
 
@@ -82,14 +84,14 @@ extern "C" {
     if (packet_flag & controller_control_packet_flag_binary_d) {
       status = controller_control_respond_error_string(global, control, F_supported_not, "Binary is not a currently supported packet mode.");
 
-      f_socket_disconnect(&client, f_socket_close_fast_e);
+      f_socket_disconnect(&control->client, f_socket_close_fast_e);
 
       if (F_status_is_error(status)) return status;
 
       return F_supported_not;
     }
 
-    client.size_read = controller_control_default_socket_buffer_d;
+    control->client.size_read = controller_control_default_socket_buffer_d;
 
     // Pre-allocate the input buffer.
     status = f_string_dynamic_increase_by(packet_length, &control->input);
@@ -97,7 +99,7 @@ extern "C" {
     if (F_status_is_error(status)) {
       controller_control_respond_error_string(global, control, F_memory_not, "Failure allocating memory.");
 
-      f_socket_disconnect(&client, f_socket_close_fast_e);
+      f_socket_disconnect(&control->client, f_socket_close_fast_e);
 
       controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true);
 
@@ -108,23 +110,23 @@ extern "C" {
       size_t total = 0;
 
       do {
-        status = f_socket_read(&client, 0, &control->input, &total);
+        status = f_socket_read(&control->client, 0, &control->input, &total);
 
         if (F_status_is_error(status)) {
-          controller_control_respond_error_string(global, control, F_status_set_fine(status), "Failure while reading from client socket.");
+          controller_control_respond_error_string(global, control, F_status_set_fine(status), "Failure while reading from control->client socket.");
 
-          f_socket_disconnect(&client, f_socket_close_fast_e);
+          f_socket_disconnect(&control->client, f_socket_close_fast_e);
 
           return F_status_set_fine(status);
         }
 
-      } while (total == client.size_read);
+      } while (total == control->client.size_read);
     }
 
     if (control->input.used != length) {
       controller_control_respond_error_string(global, control, F_valid_not, "Received packet header length did not match actual received packet length.");
 
-      f_socket_disconnect(&client, f_socket_close_fast_e);
+      f_socket_disconnect(&control->client, f_socket_close_fast_e);
 
       return F_valid_not;
     }
@@ -133,7 +135,7 @@ extern "C" {
 
     // @todo send any responses.
 
-    f_socket_disconnect(&client, f_socket_close_fast_e);
+    f_socket_disconnect(&control->client, f_socket_close_fast_e);
 
     // Resize memory when the allocated size is greate than the maximum preferred size.
     // Resizing could potentially copy memory to a new address, so it is assumed to be cheaper to just delete the memory entirely.
@@ -308,7 +310,7 @@ extern "C" {
       if (F_status_is_error(status2)) return status2;
     }
 
-    return f_socket_write(control->client, 0, control->output.string, 0);
+    return f_socket_write(&control->client, 0, control->output.string, 0);
   }
 #endif // _di_controller_control_respond_error_
 
index b9c34d046257576cf9b534d3f83427913bab0b5e..515876319f602a0ffb759f7c8230efb27fd36abf 100644 (file)
@@ -20,7 +20,7 @@ extern "C" {
  * @param global
  *   The global data.
  * @param control
- *   The control data structure.
+ *   The control data.
  *
  * @return
  *   F_none on success.
@@ -121,10 +121,8 @@ extern "C" {
  *
  * @param global
  *   The global data.
- * @param server
- *   The server socket structure.
- * @param packet
- *   The control packet data structure.
+ * @param control
+ *   The control data.
  *
  * @return
  *   F_none on success.
@@ -152,7 +150,7 @@ extern "C" {
  * @param global
  *   The global data.
  * @param control
- *   The control structure.
+ *   The control data.
  * @param type
  *   The packet type.
  *   Set type.used to 0 to not add to the header.
@@ -198,7 +196,7 @@ extern "C" {
  * @param global
  *   The global data.
  * @param control
- *   The control structure.
+ *   The control data.
  * @param status
  *   The status code.
  * @param message
@@ -223,7 +221,7 @@ extern "C" {
  * @param global
  *   The global data.
  * @param control
- *   The control structure.
+ *   The control data.
  * @param status
  *   The status code.
  * @param message
index 1c81e7b2a3acbd68300fa0198590e0699c15e8f3..583e33abc2ca9ab2b461dd25702f1ceaacb1123b 100644 (file)
@@ -172,13 +172,12 @@ extern "C" {
 
     controller_setting_t setting = controller_setting_t_initialize;
 
-    struct sockaddr_un address;
-    setting.control_socket.address = (struct sockaddr *) &address;
-    setting.control_socket.domain = f_socket_domain_file_d;
-    setting.control_socket.type = f_socket_type_datagram_d;
-    setting.control_socket.length = sizeof(struct sockaddr_un);
+    setting.control.server.address = (struct sockaddr *) &setting.control.address;
+    setting.control.server.domain = f_socket_domain_file_d;
+    setting.control.server.type = f_socket_type_stream_d;
+    setting.control.server.length = sizeof(struct sockaddr_un);
 
-    memset(&address, 0, setting.control_socket.length);
+    memset(setting.control.server.address, 0, setting.control.server.length);
 
     if (main->parameters.remaining.used) {
       status = f_string_dynamic_append(argv[main->parameters.remaining.array[0]], &setting.name_entry);
@@ -375,18 +374,20 @@ extern "C" {
       setting.entry.show = controller_entry_show_init_e;
 
       if (main->parameters.array[controller_parameter_interruptible_e].result == f_console_result_found_e) {
-        setting.interruptible = F_true;
+        setting.flag |= controller_setting_flag_interruptible_e;
       }
-      else {
-        setting.interruptible = F_false;
+      else if (setting.flag & controller_setting_flag_interruptible_e) {
+        setting.flag -= controller_setting_flag_interruptible_e;
       }
     }
     else {
       if (main->parameters.array[controller_parameter_uninterruptible_e].result == f_console_result_found_e) {
-        setting.interruptible = F_false;
+        if (setting.flag & controller_setting_flag_interruptible_e) {
+          setting.flag -= controller_setting_flag_interruptible_e;
+        }
       }
       else {
-        setting.interruptible = F_true;
+        setting.flag |= controller_setting_flag_interruptible_e;
       }
     }
 
@@ -439,7 +440,7 @@ extern "C" {
       fll_print_dynamic_raw(f_string_eol_s, main->output.to.stream);
     }
 
-    if (status != F_child && setting.pid_created) {
+    if (status != F_child && (setting.flag & controller_setting_flag_pid_created_e)) {
       const f_status_t status_delete = controller_file_pid_delete(main->pid, setting.path_pid);
 
       if (F_status_is_error(status_delete) && main->warning.verbosity == f_console_verbosity_debug_e) {
@@ -461,9 +462,9 @@ extern "C" {
     }
 
     if (status != F_child && setting.path_control.used) {
-      f_socket_disconnect(&setting.control_socket, f_socket_close_read_write_e);
+      f_socket_disconnect(&setting.control.server, f_socket_close_read_write_e);
 
-      if (!setting.control_readonly) {
+      if (!(setting.control.flag & controller_control_flag_readonly_e)) {
         f_file_remove(setting.path_control);
       }
     }
index 2867e22b5124daed8e84c56493b6e0f64c6c4dd9..a826a2207f42e1ed9df8737d13ac4c6d1ea2352b 100644 (file)
@@ -458,7 +458,7 @@ extern "C" {
         status = F_none;
       }
       else {
-        global->setting->pid_created = F_true;
+        global->setting->flag |= controller_setting_flag_pid_created_e;
 
         if (global->main->output.verbosity == f_console_verbosity_debug_e) {
           controller_lock_print(global->main->output.to, global->thread);
@@ -472,178 +472,196 @@ extern "C" {
     }
 
     if (global->setting->path_control.used) {
-      if (global->setting->control_readonly) {
-        if (f_file_exists(global->setting->path_control) != F_true) {
-          if (global->main->output.verbosity == f_console_verbosity_debug_e) {
-            controller_lock_print(global->main->output.to, global->thread);
+      status = controller_perform_ready_socket(global, cache, is_entry);
 
-            fl_print_format("%r%[%QControl socket '%]", global->main->warning.to.stream, f_string_eol_s, global->main->warning.context, global->main->warning.prefix, global->main->warning.context);
-            fl_print_format("%[%Q%]", global->main->output.to.stream, global->main->context.set.notable, global->setting->path_control, global->main->context.set.notable);
-            fl_print_format("' .%r", global->main->output.to.stream, f_string_eol_s);
-            fl_print_format("%[' cannot be found while read only mode is enabled and so the Control socket is unavailable.%]%r", global->main->output.to.stream, global->main->warning.context, global->main->warning.context, f_string_eol_s);
+      // Do not fail on non-memory errors related to creating the control socket.
+      if (F_status_is_error(status) && F_status_set_fine(status) != F_memory) {
+        status = F_none;
+      }
+    }
 
-            controller_unlock_print_flush(global->main->output.to, global->thread);
-          }
+    return status;
+  }
+#endif // _di_controller_perform_ready_
 
-          return status;
+#ifndef _di_controller_perform_ready_socket_
+  f_status_t controller_perform_ready_socket(const controller_global_t * const global, controller_cache_t * const cache, const bool is_entry) {
+
+    f_status_t status = F_none;
+
+    if (global->setting->control.flag & controller_control_flag_readonly_e) {
+      if (f_file_exists(global->setting->path_control) != F_true) {
+        if (global->main->output.verbosity == f_console_verbosity_debug_e) {
+          controller_lock_print(global->main->output.to, global->thread);
+
+          fl_print_format("%r%[%QControl socket '%]", global->main->warning.to.stream, f_string_eol_s, global->main->warning.context, global->main->warning.prefix, global->main->warning.context);
+          fl_print_format("%[%Q%]", global->main->output.to.stream, global->main->context.set.notable, global->setting->path_control, global->main->context.set.notable);
+          fl_print_format("' .%r", global->main->output.to.stream, f_string_eol_s);
+          fl_print_format("%[' cannot be found while read only mode is enabled and so the Control socket is unavailable.%]%r", global->main->output.to.stream, global->main->warning.context, global->main->warning.context, f_string_eol_s);
+
+          controller_unlock_print_flush(global->main->output.to, global->thread);
         }
+
+        return F_data_not;
       }
-      else {
-        status = f_socket_create(&global->setting->control_socket);
+    }
 
-        if (F_status_is_error(status)) {
-          if (F_status_set_fine(status) == F_memory_not) {
-            controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_socket_create", F_true);
+    status = f_socket_create(&global->setting->control.server);
 
-            return status;
-          }
+    if (F_status_is_error(status)) {
+      if (F_status_set_fine(status) == F_memory_not) {
+        controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_socket_create", F_true);
+      }
+      else if (global->main->output.verbosity == f_console_verbosity_debug_e) {
+        controller_lock_print(global->main->output.to, global->thread);
 
-          if (global->main->output.verbosity == f_console_verbosity_debug_e) {
-            controller_lock_print(global->main->output.to, global->thread);
+        fl_print_format("%r%[%QControl socket '%]", global->main->warning.to.stream, f_string_eol_s, global->main->warning.context, global->main->warning.prefix, global->main->warning.context);
+        fl_print_format("%[%Q%]", global->main->output.to.stream, global->main->context.set.notable, global->setting->path_control, global->main->context.set.notable);
+        fl_print_format("%[' could not be created, code %]", global->main->output.to.stream, global->main->warning.context, global->main->warning.context);
+        fl_print_format("%[%ui%]", global->main->output.to.stream, global->main->context.set.notable, F_status_set_fine(status), global->main->context.set.notable);
+        fl_print_format("%[.%]%r", global->main->output.to.stream, global->main->warning.context, global->main->warning.context, f_string_eol_s);
 
-            fl_print_format("%r%[%QControl socket '%]", global->main->warning.to.stream, f_string_eol_s, global->main->warning.context, global->main->warning.prefix, global->main->warning.context);
-            fl_print_format("%[%Q%]", global->main->output.to.stream, global->main->context.set.notable, global->setting->path_control, global->main->context.set.notable);
-            fl_print_format("%[' could not be created, code %]", global->main->output.to.stream, global->main->warning.context, global->main->warning.context);
-            fl_print_format("%[%ui%]", global->main->output.to.stream, global->main->context.set.notable, F_status_set_fine(status), global->main->context.set.notable);
-            fl_print_format("%[.%]%r", global->main->output.to.stream, global->main->warning.context, global->main->warning.context, f_string_eol_s);
+        controller_unlock_print_flush(global->main->output.to, global->thread);
+      }
 
-            controller_unlock_print_flush(global->main->output.to, global->thread);
-          }
-        }
-        else {
-          status = f_file_remove(global->setting->path_control);
+      return status;
+    }
 
-          if (F_status_set_fine(status) == F_memory_not) {
-            controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_file_remove", F_true);
+    if (!(global->setting->control.flag & controller_control_flag_readonly_e)) {
+      status = f_file_remove(global->setting->path_control);
 
-            return status;
-          }
+      if (F_status_set_fine(status) == F_memory_not) {
+        controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_file_remove", F_true);
 
-          global->setting->control_socket.name = global->setting->path_control.string;
+        return status;
+      }
+    }
 
-          status = f_socket_bind_file(global->setting->control_socket);
+    global->setting->control.server.name = global->setting->path_control.string;
 
-          if (F_status_is_error(status)) {
-            f_socket_disconnect(&global->setting->control_socket, f_socket_close_fast_e);
+    status = f_socket_bind_local(&global->setting->control.server);
 
-            if (F_status_set_fine(status) == F_memory_not) {
-              controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_socket_bind_file", F_true);
+    if (F_status_is_error(status)) {
+      f_socket_disconnect(&global->setting->control.server, f_socket_close_fast_e);
 
-              return status;
-            }
+      if (!(global->setting->control.flag & controller_control_flag_readonly_e)) {
+        f_file_remove(global->setting->path_control);
+      }
 
-            if (global->main->output.verbosity == f_console_verbosity_debug_e) {
-              controller_lock_print(global->main->output.to, global->thread);
+      if (F_status_set_fine(status) == F_memory_not) {
+        controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_socket_bind_local", F_true);
+      }
+      else if (global->main->output.verbosity == f_console_verbosity_debug_e) {
+        controller_lock_print(global->main->output.to, global->thread);
 
-              fl_print_format("%r%[%QControl socket '%]", global->main->warning.to.stream, f_string_eol_s, global->main->warning.context, global->main->warning.prefix, global->main->warning.context);
-              fl_print_format("%[%Q%]", global->main->output.to.stream, global->main->context.set.notable, global->setting->path_control, global->main->context.set.notable);
-              fl_print_format("%[' could not be bound, code %]", global->main->output.to.stream, global->main->warning.context, global->main->warning.context);
-              fl_print_format("%[%ui%]", global->main->output.to.stream, global->main->context.set.notable, F_status_set_fine(status), global->main->context.set.notable);
-              fl_print_format("%[.%]%r", global->main->output.to.stream, global->main->warning.context, global->main->warning.context, f_string_eol_s);
+        fl_print_format("%r%[%QControl socket '%]", global->main->warning.to.stream, f_string_eol_s, global->main->warning.context, global->main->warning.prefix, global->main->warning.context);
+        fl_print_format("%[%Q%]", global->main->output.to.stream, global->main->context.set.notable, global->setting->path_control, global->main->context.set.notable);
+        fl_print_format("%[' could not be bound, code %]", global->main->output.to.stream, global->main->warning.context, global->main->warning.context);
+        fl_print_format("%[%ui%]", global->main->output.to.stream, global->main->context.set.notable, F_status_set_fine(status), global->main->context.set.notable);
+        fl_print_format("%[.%]%r", global->main->output.to.stream, global->main->warning.context, global->main->warning.context, f_string_eol_s);
 
-              controller_unlock_print_flush(global->main->output.to, global->thread);
-            }
-          }
-          else {
-            status = f_file_role_change(global->setting->path_control, global->setting->control_user, global->setting->control_group, F_true);
+        controller_unlock_print_flush(global->main->output.to, global->thread);
+      }
 
-            if (F_status_is_error(status)) {
-              f_socket_disconnect(&global->setting->control_socket, f_socket_close_fast_e);
+      return status;
+    }
 
-              if (F_status_set_fine(status) == F_memory_not) {
-                controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_file_role_change", F_true);
+    if (global->setting->control.flag & (controller_control_flag_has_user_e | controller_control_flag_has_group_e)) {
+      status = f_file_role_change(global->setting->path_control, global->setting->control.user, global->setting->control.group, F_true);
 
-                return status;
-              }
+      if (F_status_is_error(status)) {
+        f_socket_disconnect(&global->setting->control.server, f_socket_close_fast_e);
 
-              if (global->main->output.verbosity == f_console_verbosity_debug_e) {
-                controller_lock_print(global->main->output.to, global->thread);
+        if (!(global->setting->control.flag & controller_control_flag_readonly_e)) {
+          f_file_remove(global->setting->path_control);
+        }
 
-                fl_print_format("%r%[%QControl socket '%]", global->main->warning.to.stream, f_string_eol_s, global->main->warning.context, global->main->warning.prefix, global->main->warning.context);
-                fl_print_format("%[%Q%]", global->main->output.to.stream, global->main->context.set.notable, global->setting->path_control, global->main->context.set.notable);
-                fl_print_format("%[' failed to set file roles, code %]", global->main->output.to.stream, global->main->warning.context, global->main->warning.context);
-                fl_print_format("%[%ui%]", global->main->output.to.stream, global->main->context.set.notable, F_status_set_fine(status), global->main->context.set.notable);
-                fl_print_format("%[.%]%r", global->main->output.to.stream, global->main->warning.context, global->main->warning.context, f_string_eol_s);
+        if (F_status_set_fine(status) == F_memory_not) {
+          controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_file_role_change", F_true);
+        }
+        else if (global->main->output.verbosity == f_console_verbosity_debug_e) {
+          controller_lock_print(global->main->output.to, global->thread);
 
-                controller_unlock_print_flush(global->main->output.to, global->thread);
-              }
-            }
-            else {
-              status = f_file_mode_set(global->setting->path_control, global->setting->control_mode);
+          fl_print_format("%r%[%QControl socket '%]", global->main->warning.to.stream, f_string_eol_s, global->main->warning.context, global->main->warning.prefix, global->main->warning.context);
+          fl_print_format("%[%Q%]", global->main->output.to.stream, global->main->context.set.notable, global->setting->path_control, global->main->context.set.notable);
+          fl_print_format("%[' failed to set file roles, code %]", global->main->output.to.stream, global->main->warning.context, global->main->warning.context);
+          fl_print_format("%[%ui%]", global->main->output.to.stream, global->main->context.set.notable, F_status_set_fine(status), global->main->context.set.notable);
+          fl_print_format("%[.%]%r", global->main->output.to.stream, global->main->warning.context, global->main->warning.context, f_string_eol_s);
 
-              if (F_status_is_error(status)) {
-                f_socket_disconnect(&global->setting->control_socket, f_socket_close_fast_e);
+          controller_unlock_print_flush(global->main->output.to, global->thread);
+        }
 
-                if (F_status_set_fine(status) == F_memory_not) {
-                  controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_file_role_change", F_true);
+        return status;
+      }
+    }
 
-                  return status;
-                }
+    if (global->setting->control.flag & controller_control_flag_has_mode_e) {
+      status = f_file_mode_set(global->setting->path_control, global->setting->control.mode);
 
-                if (global->main->output.verbosity == f_console_verbosity_debug_e) {
-                  controller_lock_print(global->main->output.to, global->thread);
+      if (F_status_is_error(status)) {
+        f_socket_disconnect(&global->setting->control.server, f_socket_close_fast_e);
 
-                  fl_print_format("%r%[%QControl socket '%]", global->main->warning.to.stream, f_string_eol_s, global->main->warning.context, global->main->warning.prefix, global->main->warning.context);
-                  fl_print_format("%[%Q%]", global->main->output.to.stream, global->main->context.set.notable, global->setting->path_control, global->main->context.set.notable);
-                  fl_print_format("%[' failed to set file mode, code %]", global->main->output.to.stream, global->main->warning.context, global->main->warning.context);
-                  fl_print_format("%[%ui%]", global->main->output.to.stream, global->main->context.set.notable, F_status_set_fine(status), global->main->context.set.notable);
-                  fl_print_format("%[.%]%r", global->main->output.to.stream, global->main->warning.context, global->main->warning.context, f_string_eol_s);
+        if (!(global->setting->control.flag & controller_control_flag_readonly_e)) {
+          f_file_remove(global->setting->path_control);
+        }
 
-                  controller_unlock_print_flush(global->main->output.to, global->thread);
-                }
-              }
-              else {
-                if (global->main->output.verbosity == f_console_verbosity_debug_e) {
-                  controller_lock_print(global->main->output.to, global->thread);
+        if (F_status_set_fine(status) == F_memory_not) {
+          controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_file_role_change", F_true);
+        }
+        else if (global->main->output.verbosity == f_console_verbosity_debug_e) {
+          controller_lock_print(global->main->output.to, global->thread);
 
-                  fl_print_format("%rControl socket '", global->main->output.to.stream, f_string_eol_s);
-                  fl_print_format("%[%Q%]", global->main->output.to.stream, global->main->context.set.notable, global->setting->path_control, global->main->context.set.notable);
-                  fl_print_format("' created.%r", global->main->output.to.stream, f_string_eol_s);
+          fl_print_format("%r%[%QControl socket '%]", global->main->warning.to.stream, f_string_eol_s, global->main->warning.context, global->main->warning.prefix, global->main->warning.context);
+          fl_print_format("%[%Q%]", global->main->output.to.stream, global->main->context.set.notable, global->setting->path_control, global->main->context.set.notable);
+          fl_print_format("%[' failed to set file mode, code %]", global->main->output.to.stream, global->main->warning.context, global->main->warning.context);
+          fl_print_format("%[%ui%]", global->main->output.to.stream, global->main->context.set.notable, F_status_set_fine(status), global->main->context.set.notable);
+          fl_print_format("%[.%]%r", global->main->output.to.stream, global->main->warning.context, global->main->warning.context, f_string_eol_s);
 
-                  controller_unlock_print_flush(global->main->output.to, global->thread);
-                }
+          controller_unlock_print_flush(global->main->output.to, global->thread);
+        }
 
-                status = f_thread_create(0, &global->thread->id_listen, &controller_thread_control_listen, (void *) global);
+        return status;
+      }
+    }
 
-                if (status == F_child) {
-                  return status;
-                }
+    if (global->main->output.verbosity == f_console_verbosity_debug_e) {
+      controller_lock_print(global->main->output.to, global->thread);
 
-                if (F_status_is_error_not(status)) {
-                  status = f_thread_create(0, &global->thread->id_control, &controller_thread_control, (void *) global);
+      fl_print_format("%rControl socket '", global->main->output.to.stream, f_string_eol_s);
+      fl_print_format("%[%Q%]", global->main->output.to.stream, global->main->context.set.notable, global->setting->path_control, global->main->context.set.notable);
+      fl_print_format("' created.%r", global->main->output.to.stream, f_string_eol_s);
 
-                  if (status == F_child) {
-                    return status;
-                  }
-                }
+      controller_unlock_print_flush(global->main->output.to, global->thread);
+    }
 
-                if (F_status_is_error(status)) {
-                  if (global->thread->id_listen) {
-                    f_thread_cancel(global->thread->id_listen);
-                    f_thread_join(global->thread->id_listen, 0);
+    status = f_thread_create(0, &global->thread->id_control, &controller_thread_control, (void *) global);
 
-                    global->thread->id_listen = 0;
-                  }
+    if (status == F_child) {
+      return status;
+    }
 
-                  global->thread->id_control = 0;
+    if (F_status_is_error(status)) {
+      f_socket_disconnect(&global->setting->control.server, f_socket_close_fast_e);
 
-                  if (global->main->error.verbosity != f_console_verbosity_quiet_e) {
-                    controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_thread_create", F_true);
-                  }
-                }
-              }
-            }
-          }
-        }
+      if (!(global->setting->control.flag & controller_control_flag_readonly_e)) {
+        f_file_remove(global->setting->path_control);
+      }
 
-        // Don't fail if unable to create socket file.
-        status = F_none;
+      if (global->thread->id_control) {
+        f_thread_cancel(global->thread->id_control);
+        f_thread_join(global->thread->id_control, 0);
+
+        global->thread->id_control = 0;
+      }
+
+      if (global->main->error.verbosity != f_console_verbosity_quiet_e) {
+        controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_thread_create", F_true);
       }
     }
 
-    return status;
+    return F_none;
   }
-#endif // _di_controller_perform_ready_
+#endif // _di_controller_perform_ready_socket_
 
 #ifndef _di_controller_status_simplify_error_
   f_status_t controller_status_simplify_error(const f_status_t status) {
@@ -725,7 +743,7 @@ extern "C" {
   int controller_time_sleep_nanoseconds(controller_main_t * const main, controller_setting_t * const setting, struct timespec time) {
 
     // When sleep is a second or more, instead wait for terminating signals if interruptible.
-    if (setting->interruptible && time.tv_sec) {
+    if ((setting->flag & controller_setting_flag_interruptible_e) && time.tv_sec) {
       siginfo_t information;
       f_signal_t signal = f_signal_t_initialize;
 
index cbab56db13fcc088bf57bc47fc08fad30f4ba703..ef956d7b1b23e81dfc12be55f45693ae42abc753 100644 (file)
@@ -250,6 +250,43 @@ extern "C" {
 #endif // _di_controller_perform_ready_
 
 /**
+ * Perform the socket loading when "ready".
+ *
+ * This prints messages on errors.
+ *
+ * This does not do any locking or unlocking for the setting data, be sure to lock appropriately before and after calling this.
+ *
+ * @param global
+ *   The global data.
+ * @param cache
+ *   The cache.
+ * @param is_entry
+ *   If TRUE, then this operate as an entry.
+ *   If FALSE, then this operate as an exit.
+ *
+ * @return
+ *   F_none on success.
+ *   F_data_not on success but socket file not created.
+ *
+ *   Errors (with error bit) from: f_file_mode_set().
+ *   Errors (with error bit) from: f_file_remove().
+ *   Errors (with error bit) from: f_file_role_change().
+ *   Errors (with error bit) from: f_socket_bind_local().
+ *   Errors (with error bit) from: f_socket_create().
+ *   Errors (with error bit) from: f_thread_create().
+ *
+ * @see f_file_mode_set()
+ * @see f_file_remove()
+ * @see f_file_role_change()
+ * @see f_socket_bind_local()
+ * @see f_socket_create()
+ * @see f_thread_create()
+ */
+#ifndef _di_controller_perform_ready_socket_
+  extern f_status_t controller_perform_ready_socket(const controller_global_t * const global, controller_cache_t * const cache, const bool is_entry) F_attribute_visibility_internal_d;
+#endif // _di_controller_perform_ready_socket_
+
+/**
  * Given a wide range of status codes (that are errors), simplify them down to a small subset.
  *
  * @param status
index 57b1884823ac7256f7f2e5f565ea10ac5a003edf..9c198688b33334c5a5a96a8c0d7b454122dcf39a 100644 (file)
@@ -1486,7 +1486,7 @@ extern "C" {
               return F_status_is_error(F_critical);
             }
             else {
-              global->setting->failsafe_enabled = F_true;
+              global->setting->flag |= controller_setting_flag_failsafe_e;
               global->setting->failsafe_item_id = entry_action->number;
 
               controller_entry_preprocess_print_simulate_setting_value(*global, is_entry, controller_failsafe_s, f_string_empty_s, entry->items.array[global->setting->failsafe_item_id].name, f_string_empty_s);
@@ -2000,8 +2000,6 @@ extern "C" {
         if (F_status_is_error(status)) {
           controller_entry_print_error(is_entry, global.main->error, cache->action, F_status_set_fine(status), "fl_string_dynamic_partial_rip_nulless", F_true, global.thread);
 
-          global.setting->path_control.used = 0;
-
           break;
         }
 
@@ -2039,7 +2037,8 @@ extern "C" {
           continue;
         }
 
-        global.setting->control_group = number;
+        global.setting->control.group = number;
+        global.setting->control.flag |= controller_control_flag_has_group_e;
       }
       else if (is_entry && fl_string_dynamic_compare(controller_control_mode_s, cache->action.name_action) == F_equal_to) {
         mode_t mode = 0;
@@ -2072,7 +2071,8 @@ extern "C" {
           continue;
         }
 
-        global.setting->control_mode = mode;
+        global.setting->control.mode = mode;
+        global.setting->control.flag |= controller_control_flag_has_mode_e;
       }
       else if (is_entry && fl_string_dynamic_compare(controller_control_user_s, cache->action.name_action) == F_equal_to) {
         uid_t number = 0;
@@ -2098,7 +2098,8 @@ extern "C" {
           continue;
         }
 
-        global.setting->control_user = number;
+        global.setting->control.user = number;
+        global.setting->control.flag |= controller_control_flag_has_user_e;
       }
       else if (is_entry && fl_string_dynamic_compare(controller_mode_s, cache->action.name_action) == F_equal_to) {
         if (cache->content_actions.array[i].used != 1) {
index ecc0e52e551e9cd40821f60b0adcec482cb7368e..110dcc747ee90e412c7b1fadb76813962adeba10 100644 (file)
@@ -11,10 +11,13 @@ extern "C" {
 #ifndef _di_controller_lock_create_
   f_status_t controller_lock_create(controller_lock_t *lock) {
 
-    f_status_t status = f_thread_mutex_create(0, &lock->print);
+    f_status_t status = f_thread_mutex_create(0, &lock->alert);
     if (F_status_is_error(status)) return status;
 
-    status = f_thread_mutex_create(0, &lock->alert);
+    //status = f_thread_mutex_create(0, &lock->listen);
+    //if (F_status_is_error(status)) return status;
+
+    status = f_thread_mutex_create(0, &lock->print);
     if (F_status_is_error(status)) return status;
 
     status = f_thread_lock_create(0, &lock->process);
@@ -26,6 +29,9 @@ extern "C" {
     status = f_thread_condition_create(0, &lock->alert_condition);
     if (F_status_is_error(status)) return status;
 
+    //status = f_thread_condition_create(0, &lock->listen_condition);
+    //if (F_status_is_error(status)) return status;
+
     return F_none;
   }
 #endif // _di_controller_lock_create_
index 78d1f3d181d5ed4e7fa0989515f86306009f48b4..d01d91d2e75d780f7f078253ac0801f77a880634 100644 (file)
@@ -300,20 +300,14 @@ extern "C" {
 
     controller_thread_process_exit(&global);
 
-    if (thread.id_listen) {
-      f_thread_cancel(thread.id_listen);
-    }
-
     if (thread.id_signal) f_thread_join(thread.id_signal, 0);
     if (thread.id_cleanup) f_thread_join(thread.id_cleanup, 0);
     if (thread.id_control) f_thread_join(thread.id_control, 0);
-    if (thread.id_listen) f_thread_join(thread.id_listen, 0);
     if (thread.id_entry) f_thread_join(thread.id_entry, 0);
     if (thread.id_rule) f_thread_join(thread.id_rule, 0);
 
     thread.id_cleanup = 0;
     thread.id_control = 0;
-    thread.id_listen = 0;
     thread.id_entry = 0;
     thread.id_rule = 0;
     thread.id_signal = 0;
index fd3b5dd7cbbcfe2967dc182c386d3d54ca6944d4..8a2098a85454e06645f7c9995062e68d948f50b4 100644 (file)
@@ -1,6 +1,7 @@
 #include "../controller.h"
 #include "../common/private-common.h"
 #include "../control/private-control.h"
+#include "../controller/private-controller.h"
 #include "../controller/private-controller_print.h"
 #include "private-thread.h"
 #include "private-thread_control.h"
@@ -19,73 +20,77 @@ extern "C" {
     if (global->thread->enabled != controller_thread_enabled_e) return 0;
 
     f_status_t status = F_none;
-    controller_control_t control = macro_controller_control_t_initialize(&global->setting->control_socket, 0);
+    struct timespec time;
+    controller_control_t *control = &global->setting->control;
 
     do {
 
-      // Shrink any overly large buffers.
-      if (control.cache_1.size > controller_control_default_socket_cache_d) {
-        status = f_string_dynamic_resize(controller_control_default_socket_cache_d, &control.cache_1);
+      // Remove any overly large buffers.
+      if (control->cache_1.size > controller_control_default_socket_cache_d) {
+        status = f_string_dynamic_resize(0, &control->cache_1);
       }
 
-      if (F_status_is_error_not(status) && control.cache_2.size > controller_control_default_socket_buffer_d) {
-        status = f_string_dynamic_resize(controller_control_default_socket_buffer_d, &control.cache_2);
+      if (F_status_is_error_not(status) && control->cache_2.size > controller_control_default_socket_buffer_d) {
+        status = f_string_dynamic_resize(0, &control->cache_2);
       }
 
-      if (F_status_is_error_not(status) && control.cache_3.size > controller_control_default_socket_buffer_d) {
-        status = f_string_dynamic_resize(controller_control_default_socket_buffer_d, &control.cache_3);
+      if (F_status_is_error_not(status) && control->cache_3.size > controller_control_default_socket_buffer_d) {
+        status = f_string_dynamic_resize(0, &control->cache_3);
       }
 
-      if (F_status_is_error_not(status) && control.input.size > controller_control_default_socket_buffer_d) {
-        status = f_string_dynamic_resize(controller_control_default_socket_buffer_d, &control.input);
+      if (F_status_is_error_not(status) && control->input.size > controller_control_default_socket_buffer_d) {
+        status = f_string_dynamic_resize(0, &control->input);
       }
 
-      if (F_status_is_error_not(status) && control.output.size > controller_control_default_socket_buffer_d) {
-        status = f_string_dynamic_resize(controller_control_default_socket_buffer_d, &control.output);
+      if (F_status_is_error_not(status) && control->output.size > controller_control_default_socket_buffer_d) {
+        status = f_string_dynamic_resize(0, &control->output);
       }
 
       if (F_status_is_error(status)) {
         controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_string_dynamic_resize", F_true);
+
+        status = F_none;
       }
 
-      status = controller_control_accept(global, &control);
+      status = f_socket_listen(&control->server, controller_control_default_socket_backlog_d);
 
       if (F_status_is_error(status)) {
-        controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "controller_control_accept", F_true);
-      }
+        controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_socket_listen", F_true);
 
-    } while (F_status_is_fine(status) && status != F_child && global->thread->enabled == controller_thread_enabled_e);
+        /*controller_time(controller_thread_wait_timeout_2_seconds_d, controller_thread_wait_timeout_2_nanoseconds_d, &time);
 
-    controller_control_delete_simple(&control);
+        controller_time_sleep_nanoseconds(global->main, global->setting, time);
+        */
 
-    return 0;
-  }
-#endif // _di_controller_thread_control_
+        status = F_none;
 
-#ifndef _di_controller_thread_control_listen_
-  void * controller_thread_control_listen(void * const arguments) {
+        continue;
+      }
 
-    f_thread_cancel_state_set(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
+      status = controller_control_accept(global, control);
+      if (status == F_child) break;
 
-    const controller_global_t *global = (controller_global_t *) arguments;
-
-    if (global->thread->enabled != controller_thread_enabled_e) return 0;
+      if (F_status_is_error(status)) {
+        controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "controller_control_accept", F_true);
+      }
 
-    if (global->setting->interruptible) {
-      f_signal_mask(SIG_UNBLOCK, &global->main->signal.set, 0);
-    }
+      status = F_none;
 
-    f_socket_t * const server = &global->setting->control_socket;
+    } while (global->thread->enabled == controller_thread_enabled_e);
 
-    const f_status_t status = f_socket_listen(server, controller_control_default_socket_backlog_d);
+    if (status == F_child) {
 
-    if (F_status_is_error(status)) {
-      controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_socket_listen", F_true);
+      // A forked child process should deallocate memory on exit.
+      // It seems that this function doesn't return to the calling thread for a forked child process, even with the "return 0;" below.
+      // Deallocate as much as possible.
+      controller_thread_delete_simple(global->thread);
+      controller_setting_delete_simple(global->setting);
+      controller_main_delete(global->main);
     }
 
     return 0;
   }
-#endif // _di_controller_thread_control_listen_
+#endif // _di_controller_thread_control_
 
 #ifdef __cplusplus
 } // extern "C"
index b8f49d2e2d88e3ea56eff780be47f737be9a06f2..73fdc06711223a128db5b8ac3693a0d683ab9bec 100644 (file)
@@ -26,23 +26,6 @@ extern "C" {
   extern void * controller_thread_control(void * const arguments) F_attribute_visibility_internal_d;
 #endif // _di_controller_thread_control_
 
-/**
- * Thread for handling the control listener.
- *
- * This runs on a separate thread entirely to be interuptable and closable distinctly from the main control thread.
- * This is simple and has nothing that needs to be cleaned up and so immediately exits on cancel.
- *
- * @param arguments
- *   The thread arguments.
- *   Must be of type controller_global_t.
- *
- * @return
- *   0, always.
- */
-#ifndef _di_controller_thread_control_listen_
-  extern void * controller_thread_control_listen(void * const arguments) F_attribute_visibility_internal_d;
-#endif // _di_controller_thread_control_listen_
-
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 22da8dcb945d4e6ff0a6b5cf6978e2ba2ec4583f..ea080c4592fb00c280e2a32874f876c65f2a3de9 100644 (file)
@@ -58,7 +58,7 @@ extern "C" {
           if (F_status_is_error(*status)) {
             entry->setting->ready = controller_setting_ready_fail_e;
 
-            if ((F_status_set_fine(*status) == F_execute || F_status_set_fine(*status) == F_require) && entry->global->setting->failsafe_enabled) {
+            if ((F_status_set_fine(*status) == F_execute || F_status_set_fine(*status) == F_require) && (entry->global->setting->flag & controller_setting_flag_failsafe_e)) {
               const uint8_t original_enabled = entry->global->thread->enabled;
 
               // Restore operating mode so that the failsafe can execute.
@@ -82,7 +82,7 @@ extern "C" {
                   controller_lock_print(main->error.to, entry->global->thread);
 
                   fl_print_format("%r%[%QFailed while processing requested failsafe item '%]", main->error.to.stream, f_string_eol_s, main->error.context, main->error.prefix, main->error.context);
-                  fl_print_format("%[%Q%]", main->error.to.stream, main->error.notable, entry->global->setting->entry.items.array[entry->global->setting->failsafe_enabled].name, main->error.notable);
+                  fl_print_format("%[%Q%]", main->error.to.stream, main->error.notable, entry->global->setting->entry.items.array[entry->global->setting->failsafe_item_id].name, main->error.notable);
                   fl_print_format("%['.%]%r", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s);
 
                   controller_unlock_print_flush(main->error.to, entry->global->thread);
@@ -170,7 +170,7 @@ extern "C" {
         if (F_status_is_error(*status)) {
           entry->setting->ready = controller_setting_ready_fail_e;
 
-          if ((F_status_set_fine(*status) == F_execute || F_status_set_fine(*status) == F_require) && entry->global->setting->failsafe_enabled) {
+          if ((F_status_set_fine(*status) == F_execute || F_status_set_fine(*status) == F_require) && (entry->global->setting->flag & controller_setting_flag_failsafe_e)) {
 
             const uint8_t original_enabled = entry->global->thread->enabled;
 
@@ -197,7 +197,7 @@ extern "C" {
                 controller_lock_print(main->error.to, entry->global->thread);
 
                 fl_print_format("%r%[%QFailed while processing requested failsafe item '%]", main->error.to.stream, f_string_eol_s, main->error.context, main->error.prefix, main->error.context);
-                fl_print_format("%[%Q%]", main->error.to.stream, main->error.notable, entry->global->setting->entry.items.array[entry->global->setting->failsafe_enabled].name, main->error.notable);
+                fl_print_format("%[%Q%]", main->error.to.stream, main->error.notable, entry->global->setting->entry.items.array[entry->global->setting->failsafe_item_id].name, main->error.notable);
                 fl_print_format("%['.%]%r", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s);
 
                 controller_unlock_print_flush(main->error.to, entry->global->thread);
@@ -234,7 +234,6 @@ extern "C" {
       // A forked child process should deallocate memory on exit.
       // It seems that this function doesn't return to the calling thread for a forked child process, even with the "return 0;" below.
       // Deallocate as much as possible.
-
       controller_thread_delete_simple(entry->global->thread);
       controller_setting_delete_simple(entry->global->setting);
       controller_main_delete(entry->global->main);
index f0210fa9c5146a65bf16d9a9bfa1ebff0dea66d4..5ce3c88c024ced9eea5ee89025ab34d6e77214d2 100644 (file)
@@ -90,6 +90,13 @@ extern "C" {
       global.thread->id_cleanup = 0;
     }
 
+    if (global.thread->id_control) {
+      f_thread_cancel(global.thread->id_control);
+      f_thread_join(global.thread->id_control, 0);
+
+      global.thread->id_control = 0;
+    }
+
     // The sigtimedwait() function that is run inside of signal must be interrupted via the f_thread_cancel().
     if (by != controller_thread_cancel_signal_e && global.thread->id_signal) {
       f_thread_cancel(global.thread->id_signal);
index 7684780a2eb062e417c6f446d54a7f2a9498207e..75cbc29aae999308d9eba3175d54111bf5db4ca7 100644 (file)
@@ -29,7 +29,7 @@ extern "C" {
         if (errno == EAGAIN) continue;
       }
 
-      if (global->setting->interruptible) {
+      if (global->setting->flag & controller_setting_flag_interruptible_e) {
         if (information.si_signo == F_signal_interrupt || information.si_signo == F_signal_abort || information.si_signo == F_signal_quit || information.si_signo == F_signal_termination) {
           global->thread->signal = information.si_signo;
 
index 53fd8a4cbe66e325019284492d0bdc85f5e4ee06..f01568050b66245b23c69d8e1437495009a60f2c 100644 (file)
@@ -9,24 +9,67 @@ Packet Documentation:
   The "packet" is the general category in which multiple types of packets belong.
   This describes the different packets based on their "type".
 
-  Every packet contains a "header", a "type" within the header, a "length" within the header, and a "payload".
+  Each packet begins with a control block and a size block followed by a payload block.
 
-  The "controller" packet type\:
-    Commands being sent to the controller and their respective responses utilize a "controller" packet.
+    The control block\:
+      The leading bit (starting from the left) designates the the format of the payload, which is 0 for string and 1 for binary.
+      The second bit (starting from the left) designates the the byte order for the rest of the packet, which 0 is for little endian and 1 is for big endian.
+      The remaining 6-bits are reserved for future use.
+
+    The size block\:
+      The size block represents the size of the entire packet (the control block, the size blocks, and the payload block).
+      This number is an 32-bit unsigned integer.
+      The size block may contain up to 4 32-bit unsigned integers.
+      If the size is less than the max value of a 32-bit integer (4294967295), then the remaining 32-bit unsigned integers may be omitted.
+
+      Example size that is less than 2^32-1\:
+        [ control block ] [ size block                                  ] [ payload block         ]
+        [ 0b10000000    ] [ 0b00000000 0b00000000 0b00000100 0b11010010 ] [ size: 1229 (1234 - 5) ]
+
+      Example size that is less than 2^64-1\:
+        [ control block ] [ size block                                  ] [ size block                                  ] [ payload block                     ]
+        [ 0b10000000    ] [ 0b11111111 0b11111111 0b11111111 0b11111111 ] [ 0b00000000 0b00000000 0b00000000 0b11001000 ] [ size: 4294967486 (4294967495 - 9) ]
+
+    The payload block\:
+      This block is represented by the FSS-000e payload specification and its structure ad use is described in the next sections.
+
+      The following types of payload are received or sent\:
+      1) controller payload.
+      2) error payload.
+
+  The controller payload\:
+    Commands being sent to the controller and their respective responses utilize a "controller" payload.
     These are pre-defined commands to rules or the controller program itself.
     Commands such as starting or stopping some rule, for example.
+    A controller payload is also sent in response to a controller payload request to represent a success.
 
     When operating in "init" mode, additional commands are available: "reboot" and "shutdown".
-    The "reboot" is for rebooting the machine and will eventually support "kexec" mode.
-    The "shutdown" is for shutting down the machine.
-    These two commands are configurable to fire off based on conditions, namely "time".
-    Two conditions may be met "on or after a specific date and time" and/or after so many milliseconds (second, minutes, hours, days, etc..) have passed.
+    The "kexec" is for booting into another kernel, which may effectively be the same as a "reboot" (currently not supported nor implemented).
+    The "reboot" is for rebooting the machine (currently not implemented).
+    The "shutdown" is for shutting down the machine (currently not implemented).
+    These three commands are configurable to fire off based on conditions\:
+
+      The "now" condition designates that the kexec, reboot, or shutdown is to begin immediately.
+      The "at" condition designates that the kexec, reboot, or shutdown is to begin once a specific date and time is reached by the system clock.
+      The "in" condition designates that the kexec, reboot, or shutdown is to begin once a specific amount of time is passed by the system clock since the execution of this command started.
+
+    For these "time" conditions, different units of time should be supported, such as "seconds", "days", "years" as standard time, Time or UNIX Time (Epoch Time).
 
-    The normal "controller" packet commands are any valid Rule Action that performs some action.
+    The normal "controller" payload commands are any valid Rule Action that performs some action.
     This does not include Actions that provide some setting or configuration (such as "with_pid").
     Some of the supported commands are: "freeze", "kill", "pause", "reload", "rerun", "restart", "resume", "start", "stop", or "thaw".
+    Multiple commands may be sent multiple "action" headers.
+    The "action" headers are order sensitive, executing from top to bottom, and one does not start until the previous successfully completes.
+
+    Multiple "status" headers may exist in the response so long as they each match an "action" in the request.
+
+    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.
 
-  The "error" packet type\:
-    The error packet is intended to communicate some sort of failure.
-    The "status" from the "header" designates the status code (based on the FSS status codes and FLL status codes).
-    The "payload" will contain a NULL terminated string representin the message used to describe the error.
+  The error payload\:
+    The error payload is intended to communicate some sort of failure.
+    The error payload is only sent in response to some request (and not in response to another response).
+    The control (the client) is not expected to send error payloads and the controller (the service) should send an error in response to an error payload or ignore it entirely.
+    The "status" from the "header" designates the status code.
+    The "payload" will contain a NULL terminated string representing the message used to describe the error.
index 568263d701074fc84b0e5adadd80e09b80700199..b388ae075fe5e19584a054b2be7b6ddc19e1021a 100644 (file)
@@ -6,6 +6,11 @@
 Entry Specification:
   The controller program communicates use the FSS-000E Packet format.
 
+  Packet Structure\:
+    Packet is grouped into the following blocks\:
+      - control: A single 1-byte block representing contol codes.
+      - size: A set of 1 to 4 4-byte blocks representing the size of the entire packet.
+
   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".
     - length: A positive whole number inclusively between 0 and 4294965248 representing the length of the "payload".
@@ -27,11 +32,12 @@ Entry Specification:
 
     The "payload" is a NULL terminated string whose length is defined by the "length" "header" Content.
 
+  There are different headers and payload properties based on the "type".
+
   The "controller" type\:
     Supports the following headers: "action", "length", "status", and "type".
 
-    Currently only a single "action" is supported.
-    Currently only a single "status" is supported.
+    Multiple "action" may be provided, but at least one must exist.
+    Multiple "status" may be provided, but at least one must exist.
 
     The "payload" is dependent on the "action".
-    @todo describe the different actions.