]> Kevux Git Server - kevux-tools/commitdiff
Progress: Implement the threads for the receive and send.
authorKevin Day <kevin@kevux.org>
Thu, 13 Jul 2023 03:35:41 +0000 (22:35 -0500)
committerKevin Day <kevin@kevux.org>
Thu, 13 Jul 2023 03:35:41 +0000 (22:35 -0500)
This ignores the non-thread version at this time.

14 files changed:
data/build/tacocat/settings
sources/c/tacocat/main/common.c
sources/c/tacocat/main/common.h
sources/c/tacocat/main/common/define.h
sources/c/tacocat/main/common/type.c
sources/c/tacocat/main/common/type.h
sources/c/tacocat/main/process.c
sources/c/tacocat/main/process.h
sources/c/tacocat/main/receive.c [new file with mode: 0644]
sources/c/tacocat/main/receive.h [new file with mode: 0644]
sources/c/tacocat/main/send.c [new file with mode: 0644]
sources/c/tacocat/main/send.h [new file with mode: 0644]
sources/c/tacocat/main/signal.c
sources/c/tacocat/main/tacocat.h

index 3e234b7d4d9278d60f1eab0211ffc14963431029..fdbf0cb0afc1a15d084f320e6b0002f010de422b 100644 (file)
@@ -37,9 +37,9 @@ build_libraries-individual_thread -lf_thread
 build_libraries-level -lfll_2 -lfll_1 -lfll_0
 build_libraries-monolithic -lfll
 
-build_sources_library main/common.c main/common/define.c main/common/enumeration.c main/common/print.c main/common/string.c main/common/type.c main/print/error.c main/print/message.c main/print/verbose.c main/print/warning.c main/process.c main/signal.c main/tacocat.c main/thread.c
+build_sources_library main/common.c main/common/define.c main/common/enumeration.c main/common/print.c main/common/string.c main/common/type.c main/print/error.c main/print/message.c main/print/verbose.c main/print/warning.c main/process.c main/receive.c main/send.c main/signal.c main/tacocat.c main/thread.c
 
-build_sources_headers main/common.h main/common/define.h main/common/enumeration.h main/common/print.h main/common/string.h main/common/type.h main/print/error.h main/print/message.h main/print/verbose.h main/print/warning.h main/process.h main/signal.h main/tacocat.h main/thread.h
+build_sources_headers main/common.h main/common/define.h main/common/enumeration.h main/common/print.h main/common/string.h main/common/type.h main/print/error.h main/print/message.h main/print/verbose.h main/print/warning.h main/process.h main/receive.h main/send.h main/signal.h main/tacocat.h main/thread.h
 
 build_sources_program main/main.c
 
index 074994b67db599f90355e51ce3c7000abebbcd18..9fee6f0e89adcae491c4e4afb261c9c2e7ad20d0 100644 (file)
@@ -162,6 +162,11 @@ extern "C" {
       kt_tacocat_parameter_send_e,
     };
 
+    const uint64_t flags[] = {
+      kt_tacocat_main_flag_receive_e,
+      kt_tacocat_main_flag_send_e,
+    };
+
     const f_string_static_t longs[] = {
       kt_tacocat_long_receive_s,
       kt_tacocat_long_send_s,
@@ -190,6 +195,8 @@ extern "C" {
     for (uint8_t i = 0; i < 2; ++i) {
 
       if (main->program.parameters.array[parameters[i]].result & f_console_result_value_e) {
+        main->setting.flag |= flags[i];
+
         if (main->program.parameters.array[parameters[i]].values.used % 2) {
           main->setting.state.status = F_status_set_error(F_parameter);
 
@@ -475,6 +482,8 @@ extern "C" {
         } // for
       }
       else if (main->program.parameters.array[parameters[i]].result & f_console_result_found_e) {
+        main->setting.flag -= main->setting.flag & flags[i];
+
         main->setting.state.status = F_status_set_error(F_parameter);
 
         macro_setting_load_print_first();
@@ -487,6 +496,9 @@ extern "C" {
 
         continue;
       }
+      else {
+        main->setting.flag -= main->setting.flag & flags[i];
+      }
     } // for
 
     if (F_status_is_error(failed)) {
index b7a4aaf2e59b3f71ea0a2a2e01255ce9a0aaa408..80fa7e12f3e783c55a762e2f9b17cc008b635b8e 100644 (file)
@@ -31,7 +31,7 @@ extern "C" {
  *   This alters setting.state.status:
  *     F_none on success.
  *
- *     F_parameter (with error bit) on parameter error.
+ *     F_parameter (with error bit) if a parameter is invalid.
  *
  *     Errors (with error bit) from: f_console_parameter_process().
  *     Errors (with error bit) from: f_string_dynamic_append_nulless().
@@ -70,7 +70,7 @@ extern "C" {
  *   This alters main.setting.state.status:
  *     F_none on success.
  *
- *     F_parameter (with error bit) on parameter error.
+ *     F_parameter (with error bit) if a parameter is invalid.
  *
  *     Errors (with error bit) from: f_file_exists().
  *     Errors (with error bit) from: f_file_open().
@@ -111,7 +111,7 @@ extern "C" {
  *     F_data_not on success but there is nothing in the address string (address.used is 0).
  *     F_number_not on success but there is no port number.
  *
- *     F_parameter (with error bit) on parameter error.
+ *     F_parameter (with error bit) if a parameter is invalid.
  *
  *     Errors (with error bit) from: fl_conversion_dynamic_to_unsigned_detect().
  * @param address
index 771ccf200b43fce3d75a7f9f9edf6aaf35f95528..491cae37292f3bd69f58a6f91f983b7e6fc0656b 100644 (file)
@@ -35,6 +35,9 @@ extern "C" {
  * kt_tacocat_signal_*_d:
  *   - check:          When not using threads, this is how often to perform the check (lower numbers incur more kernel I/O).
  *   - check_failsafe: When using threads, how many consecutive failures to check signal before aborting (as a recursion failsafe).
+ *
+ * kt_tacocat_interval_*_d:
+ *   - poll: The time in milliseconds to poll for before returning (this is the amount of time poll() blocks).
  */
 #ifndef _di_kt_tacocat_d_
   #define kt_tacocat_allocation_console_d 4
@@ -49,6 +52,8 @@ extern "C" {
 
   #define kt_tacocat_signal_check_d          20000
   #define kt_tacocat_signal_check_failsafe_d 20000
+
+  #define kt_tacocat_interval_poll_d 1400 // 1.4 second.
 #endif // _di_kt_tacocat_d_
 
 /**
index 9afdfc2f5ef7e2f6ebd1372f85c99ec59455e302..df227fc158ba2f2114a8fb30e323ef2d2200f8dc 100644 (file)
@@ -11,6 +11,7 @@ extern "C" {
 
     fll_program_data_delete(&main->program);
     kt_tacocat_setting_delete(main->program, &main->setting);
+    kt_tacocat_thread_delete(main->program, &main->thread);
   }
 #endif // _di_kt_tacocat_main_delete_
 
@@ -53,6 +54,15 @@ extern "C" {
   }
 #endif // _di_kt_tacocat_setting_delete_
 
+#ifndef _di_kt_tacocat_thread_delete_
+  f_status_t kt_tacocat_thread_delete(const fll_program_data_t program, kt_tacocat_thread_t * const thread) {
+
+    if (!thread) return F_status_set_error(F_parameter);
+
+    return F_none;
+  }
+#endif // _di_kt_tacocat_thread_delete_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 1ca5726a9908e0c6d3fffd86a2ab286c88628f3a..f91767de717cce1d2fb0c7cf11ad9df1804552ed 100644 (file)
@@ -73,8 +73,11 @@ extern "C" {
  *
  * flag: Flags passed to the main function.
  *
- * status_thread: A status used eclusively by the threaded signal handler.
- * state:         The state data used when processing data.
+ * status_receive: A status used eclusively by the receive thread.
+ * status_send:    A status used eclusively by the send thread.
+ * status_signal:  A status used eclusively by the threaded signal handler.
+ *
+ * state: The state data used when processing data.
  *
  * receive: The socket set for receiving data receive clients.
  * send:    The socket set for sending data send clients.
@@ -85,7 +88,10 @@ extern "C" {
   typedef struct {
     uint64_t flag;
 
-    f_status_t status_thread;
+    f_status_t status_receive;
+    f_status_t status_send;
+    f_status_t status_signal;
+
     f_state_t state;
 
     kt_tacocat_socket_set_t receive;
@@ -98,6 +104,8 @@ extern "C" {
     { \
       kt_tacocat_main_flag_none_e, \
       F_none, \
+      F_none, \
+      F_none, \
       macro_f_state_t_initialize_1(kt_tacocat_allocation_large_d, kt_tacocat_allocation_small_d, F_none, 0, 0, &fll_program_standard_signal_handle, 0, 0, 0, 0), \
       macro_kt_tacocat_setting_t_initialize_1(kt_tacocat_block_size_receive_d), \
       macro_kt_tacocat_setting_t_initialize_1(kt_tacocat_block_size_send_d), \
@@ -122,17 +130,35 @@ extern "C" {
 #endif // _di_kt_tacocat_callback_t_
 
 /**
+ * The main thread settings.
+ */
+#ifndef _di_kt_tacocat_thread_t_
+  typedef struct {
+    f_thread_id_t id_receive;
+    f_thread_id_t id_send;
+  } kt_tacocat_thread_t;
+
+  #define kt_tacocat_thread_t_initialize \
+    { \
+      f_thread_id_t_initialize, \
+      f_thread_id_t_initialize, \
+    }
+#endif // _di_kt_tacocat_thread_t_
+
+/**
  * The main program data as a single structure.
  *
  * program:  The main program data.
  * setting:  The settings data.
  * callback: The program callbacks.
+ * thread:   The program thread data.
  */
 #ifndef _di_kt_tacocat_main_t_
   typedef struct {
     fll_program_data_t program;
     kt_tacocat_setting_t setting;
     kt_tacocat_callback_t callback;
+    kt_tacocat_thread_t thread;
   } kt_tacocat_main_t;
 
   #define kt_tacocat_main_t_initialize \
@@ -140,6 +166,7 @@ extern "C" {
       fll_program_data_t_initialize, \
       kt_tacocat_setting_t_initialize, \
       kt_tacocat_callback_t_initialize, \
+      kt_tacocat_thread_t_initialize, \
     }
 #endif // _di_kt_tacocat_main_t_
 
@@ -174,6 +201,23 @@ extern "C" {
   extern f_status_t kt_tacocat_setting_delete(const fll_program_data_t program, kt_tacocat_setting_t * const setting);
 #endif // _di_kt_tacocat_setting_delete_
 
+/**
+ * Delete the program main thread data.
+ *
+ * @param program
+ *   The main program data.
+ * @param thread
+ *   The program main thread data.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ */
+#ifndef _di_kt_tacocat_thread_delete_
+  extern f_status_t kt_tacocat_thread_delete(const fll_program_data_t program, kt_tacocat_thread_t * const thread);
+#endif // _di_kt_tacocat_thread_delete_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index c7f71d909a0ba4d9161924442bd172ffe0b4ebc1..9b1c8c3c1ee71045f77e13847091d43295f4d2bc 100644 (file)
@@ -8,84 +8,97 @@ extern "C" {
   void kt_tacocat_process_main(kt_tacocat_main_t * const main) {
 
     if (!main) return;
-    if (F_status_is_error(kt_tacocat_process_socket_set_error_has(main, kt_tacocat_long_receive_s, main->setting.receive))) return;
-    if (F_status_is_error(kt_tacocat_process_socket_set_error_has(main, kt_tacocat_long_send_s, main->setting.send))) return;
-
-    // @todo Make this threaded, if threading is enabled (if threading is disabled then fork).
-    //       TacocaT is intended to be simple, so be lazy and create a thread/fork for every single receive and send.
-
-    kt_tacocat_process_socket_set_receive(main);
-    kt_tacocat_process_socket_set_send(main);
-
-    // domain
-    // PF_INET = ipv4
-    // PF_INET6 = ipv6
-    // type
-    // SOCK_STREAM
-    // SOCK_DGRAM
-    // "struct sockaddr", "struct sockaddr_un", or "struct sockaddr_in"
-    // protocol
-    // f_socket_protocol_tcp
-    // f_socket_protocol_udp
-
-    //f_socket_connect
-
-    // @todo:
-    //   1: Establish connections.
-    //   2: read / write from files.
-    //   3: work or wait until told to terminate.
-    //   4: terminate.
-
-    kt_tacocat_process_socket_set_disconnect(main, &main->setting.receive);
-    kt_tacocat_process_socket_set_disconnect(main, &main->setting.send);
-
-    kt_tacocat_process_socket_set_error_handle(main, main->setting.receive);
-    kt_tacocat_process_socket_set_error_handle(main, main->setting.send);
-  }
-#endif // _di_kt_tacocat_process_main_
+    if (F_status_is_error(kt_tacocat_process_socket_set_error_has(main, kt_tacocat_long_receive_s, main->setting.receive, &main->setting.status_receive))) return;
+    if (F_status_is_error(kt_tacocat_process_socket_set_error_has(main, kt_tacocat_long_send_s, main->setting.send, &main->setting.status_send))) return;
+
+    #ifdef _di_thread_support_
+      // @todo implement fork and wait for both receive and send.
+    #else
+      {
+        if (main->setting.flag & kt_tacocat_main_flag_receive_e) {
+          memset(&main->thread.id_receive, 0, sizeof(f_thread_id_t));
+
+          main->setting.state.status = f_thread_create(0, &main->thread.id_receive, kt_tacocat_receive, (void *) main);
+        }
+
+        if (F_status_is_error_not(main->setting.state.status)) {
+          if (main->setting.flag & kt_tacocat_main_flag_send_e) {
+            memset(&main->thread.id_send, 0, sizeof(f_thread_id_t));
+
+            main->setting.state.status = f_thread_create(0, &main->thread.id_send, kt_tacocat_send, (void *) main);
+
+            if (F_status_is_error(main->setting.state.status) && (main->setting.flag & kt_tacocat_main_flag_receive_e)) {
+              f_thread_cancel(main->thread.id_receive);
+            }
+          }
+        }
+
+        if (F_status_is_error(main->setting.state.status)) {
+          kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_thread_create));
+        }
+      }
 
-#ifndef _di_kt_tacocat_process_socket_set_disconnect_
-  void kt_tacocat_process_socket_set_disconnect(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+      if (main->setting.flag & kt_tacocat_main_flag_receive_e) {
+        f_thread_join(main->thread.id_receive, 0);
 
-    if (!main) return;
+        if (F_status_is_error(main->setting.status_receive)) {
+          main->setting.state.status = main->setting.status_receive;
+        }
+      }
+
+      if (main->setting.flag & kt_tacocat_main_flag_send_e) {
+        f_thread_join(main->thread.id_send, 0);
 
-    if (!set) {
-      main->setting.state.status = F_status_set_error(F_parameter);
+        if (F_status_is_error(main->setting.status_send) && F_status_is_error_not(main->setting.state.status)) {
+          main->setting.state.status = main->setting.status_send;
+        }
+      }
+    #endif // _di_thread_support_
 
-      return;
+    if (F_status_is_error_not(main->setting.state.status)) {
+      main->setting.state.status = F_none;
     }
+  }
+#endif // _di_kt_tacocat_process_main_
+
+#ifndef _di_kt_tacocat_process_socket_set_disconnect_
+  f_status_t kt_tacocat_process_socket_set_disconnect(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+    if (!main || !set) return F_status_set_error(F_parameter);
 
     f_status_t status = F_none;
 
     for (f_number_unsigned_t i = 0; i < set->sockets.used; ++i) {
 
-      if (kt_tacocat_signal_check(main)) return;
+      if (kt_tacocat_signal_check(main)) return F_status_set_error(F_interrupt);
 
       status = f_socket_disconnect(&set->sockets.array[i], f_socket_close_read_write_e);
 
-      if (F_status_is_error_not(set->statuss.array[i]) && F_status_is_error(main->setting.state.status)) {
+      if (F_status_is_error_not(set->statuss.array[i]) && F_status_is_error(status)) {
         set->statuss.array[i] = status;
 
         kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_socket_disconnect));
       }
     } // for
+
+    return F_none;
   }
 #endif // _di_kt_tacocat_process_socket_set_disconnect_
 
 #ifndef _di_kt_tacocat_process_socket_set_error_handle_
-  void kt_tacocat_process_socket_set_error_handle(kt_tacocat_main_t * const main, const kt_tacocat_socket_set_t set) {
+  void kt_tacocat_process_socket_set_error_handle(kt_tacocat_main_t * const main, const kt_tacocat_socket_set_t set, f_status_t * const status) {
 
-    if (!main) return;
-    if (F_status_is_error(main->setting.state.status)) return;
+    if (!main || !status) return;
+    if (F_status_is_error(*status)) return;
 
-    main->setting.state.status = F_none;
+    *status = F_none;
 
     for (f_number_unsigned_t i = 0; i < set.statuss.used; ++i) {
 
       if (kt_tacocat_signal_check(main)) return;
 
       if (F_status_is_error(set.statuss.array[i])) {
-        main->setting.state.status = set.statuss.array[i];
+        *status = set.statuss.array[i];
 
         return;
       }
@@ -94,22 +107,24 @@ extern "C" {
 #endif // _di_kt_tacocat_process_socket_set_error_handle_
 
 #ifndef _di_kt_tacocat_process_socket_set_error_has_
-  f_status_t kt_tacocat_process_socket_set_error_has(kt_tacocat_main_t * const main, const f_string_static_t parameter, const kt_tacocat_socket_set_t set) {
+  f_status_t kt_tacocat_process_socket_set_error_has(kt_tacocat_main_t * const main, const f_string_static_t parameter, const kt_tacocat_socket_set_t set, f_status_t * const status) {
 
-    if (!main) {
-      main->setting.state.status = F_status_set_error(F_parameter);
+    if (!main || !status) {
+      if (status) {
+        *status = F_status_set_error(F_parameter);
+      }
 
       kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(kt_tacocat_process_socket_set_error_has));
 
-      return main->setting.state.status;
+      return F_status_set_error(F_parameter);
     }
 
     if (set.sockets.used != set.files.used || set.sockets.used != set.files.used || set.sockets.used != set.statuss.used || set.sockets.used != set.names.used || set.sockets.used != set.buffers.used) {
-      main->setting.state.status = F_status_set_error(F_parameter);
+      *status = F_status_set_error(F_parameter);
 
       kt_tacocat_print_error_setting_socket_lengths_must_match(&main->program.error, parameter, set);
 
-      return main->setting.state.status;
+      return *status;
     }
 
     return F_none;
@@ -119,9 +134,8 @@ extern "C" {
 #ifndef _di_kt_tacocat_process_socket_set_receive_
   void kt_tacocat_process_socket_set_receive(kt_tacocat_main_t * const main) {
 
-    if (!main) return;
+    if (!main || F_status_is_error(main->setting.status_receive)) return;
 
-    // Create, bind, and listen to the socket.
     for (f_number_unsigned_t i = 0; i < main->setting.receive.sockets.used; ++i) {
 
       if (kt_tacocat_signal_check(main)) return;
@@ -130,7 +144,7 @@ extern "C" {
       main->setting.receive.statuss.array[i] = f_socket_create(&main->setting.receive.sockets.array[i]);
 
       if (F_status_is_error(main->setting.receive.statuss.array[i])) {
-        main->setting.state.status = main->setting.receive.statuss.array[i];
+        main->setting.status_receive = main->setting.receive.statuss.array[i];
 
         kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_socket_create));
 
@@ -147,7 +161,7 @@ extern "C" {
         main->setting.receive.statuss.array[i] = f_socket_bind_local(&main->setting.receive.sockets.array[i]);
       }
       else {
-        main->setting.state.status = F_status_set_error(F_parameter);
+        main->setting.status_receive = F_status_set_error(F_parameter);
 
         kt_tacocat_print_error_socket_protocol_unsupported(&main->program.error, main->setting.receive.names.array[i], main->setting.receive.sockets.array[i].domain);
 
@@ -155,7 +169,7 @@ extern "C" {
       }
 
       if (F_status_is_error(main->setting.receive.statuss.array[i])) {
-        main->setting.state.status = main->setting.receive.statuss.array[i];
+        main->setting.status_receive = main->setting.receive.statuss.array[i];
 
         kt_tacocat_print_error(&main->program.error, main->setting.receive.sockets.array[i].domain == f_socket_protocol_family_inet4_e
           ? macro_kt_tacocat_f(f_socket_bind_inet4)
@@ -170,7 +184,7 @@ extern "C" {
       main->setting.receive.statuss.array[i] = f_socket_listen(&main->setting.receive.sockets.array[i], kt_tacocat_backlog_max_d);
 
       if (F_status_is_error(main->setting.receive.statuss.array[i])) {
-        main->setting.state.status = main->setting.receive.statuss.array[i];
+        main->setting.status_receive = main->setting.receive.statuss.array[i];
 
         kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_socket_listen));
 
@@ -189,13 +203,8 @@ extern "C" {
       }
     } // for
 
-    if (F_status_is_error_not(main->setting.state.status)) {
-      // @todo this is where another process should poll/wait for connections and such (in another thread/fork).
-      main->setting.state.status = f_file_poll(main->setting.receive.polls, 9000); // @todo temporarily set to 9 second(s).
-
-      // @todo handle errors, but this will be in a fork/thread.
-
-      main->setting.state.status = F_none;
+    if (F_status_is_error_not(main->setting.status_receive)) {
+      main->setting.status_receive = F_none;
     }
   }
 #endif // _di_kt_tacocat_process_socket_set_receive_
@@ -203,7 +212,7 @@ extern "C" {
 #ifndef _di_kt_tacocat_process_socket_set_send_
   void kt_tacocat_process_socket_set_send(kt_tacocat_main_t * const main) {
 
-    if (!main) return;
+    if (!main || F_status_is_error(main->setting.status_send)) return;
 
     for (f_number_unsigned_t i = 0; i < main->setting.send.sockets.used; ++i) {
 
@@ -213,7 +222,7 @@ extern "C" {
       main->setting.send.statuss.array[i] = f_socket_create(&main->setting.send.sockets.array[i]);
 
       if (F_status_is_error(main->setting.send.statuss.array[i])) {
-        main->setting.state.status = main->setting.send.statuss.array[i];
+        main->setting.status_send = main->setting.send.statuss.array[i];
 
         kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_socket_create));
 
@@ -223,8 +232,8 @@ extern "C" {
       // @todo f_socket_bind().
     } // for
 
-    if (F_status_is_error_not(main->setting.state.status)) {
-      main->setting.state.status = F_none;
+    if (F_status_is_error_not(main->setting.status_send)) {
+      main->setting.status_send = F_none;
     }
   }
 #endif // _di_kt_tacocat_process_socket_set_send_
index 7a4af94170bec5f889374530fa47d40c7e745ba0..167533fea3522f9167a21ea692e24cf569c3069b 100644 (file)
@@ -39,9 +39,14 @@ extern "C" {
  *     This does not set parameter error on success or any socket disconnect error.
  * @param set
  *   The socket set to disconnect all sockets of.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_parameter (with error bit) on invalid parameter.
  */
 #ifndef _di_kt_tacocat_process_socket_set_disconnect_
-  extern void kt_tacocat_process_socket_set_disconnect(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+  extern f_status_t kt_tacocat_process_socket_set_disconnect(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
 #endif // _di_kt_tacocat_process_socket_set_disconnect_
 
 /**
@@ -60,9 +65,11 @@ extern "C" {
  *     If this already has the error bit set, then no changes are performed.
  * @param set
  *   The socket set to handle the errors of.
+ * @param status
+ *   The status to update with the status code from the given set.
  */
 #ifndef _di_kt_tacocat_process_socket_set_error_handle_
-  extern void kt_tacocat_process_socket_set_error_handle(kt_tacocat_main_t * const main, const kt_tacocat_socket_set_t set);
+  extern void kt_tacocat_process_socket_set_error_handle(kt_tacocat_main_t * const main, const kt_tacocat_socket_set_t set, f_status_t * const status);
 #endif // _di_kt_tacocat_process_socket_set_error_handle_
 
 /**
@@ -72,21 +79,24 @@ extern "C" {
  *   The main program and settings data.
  *
  *   This alters main.setting.state.status:
- *     F_parameter (with error bit) on parameter error.
+ *     F_parameter (with error bit) if a parameter is invalid.
  *
  *     This is not altered on success.
  * @param parameter
  *   The parameter long name to use when printing errors.
  * @param set
  *   The socket set to handle the errors of.
+ * @param status
+ *   The status to update with the status code from the given set.
  *
  * @return
  *   F_none on no error.
  *
- *   F_parameter (with error bit) on parameter error.
+ *   F_interrupt (with error bit) if interrupt was received.
+ *   F_parameter (with error bit) if a parameter is invalid.
  */
 #ifndef _di_kt_tacocat_process_socket_set_error_has_
-  extern f_status_t kt_tacocat_process_socket_set_error_has(kt_tacocat_main_t * const main, const f_string_static_t parameter, const kt_tacocat_socket_set_t set);
+  extern f_status_t kt_tacocat_process_socket_set_error_has(kt_tacocat_main_t * const main, const f_string_static_t parameter, const kt_tacocat_socket_set_t set, f_status_t * const status);
 #endif // _di_kt_tacocat_process_socket_set_error_has_
 
 /**
diff --git a/sources/c/tacocat/main/receive.c b/sources/c/tacocat/main/receive.c
new file mode 100644 (file)
index 0000000..7300ec9
--- /dev/null
@@ -0,0 +1,47 @@
+#include "tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_tacocat_receive_
+  void * kt_tacocat_receive(void * const void_main) {
+
+    f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+
+    if (!void_main) return 0;
+
+    kt_tacocat_main_t * const main = (kt_tacocat_main_t *) void_main;
+
+    kt_tacocat_process_socket_set_receive(main);
+
+    if (F_status_is_error_not(main->setting.status_receive)) {
+      do {
+        main->setting.status_receive = f_file_poll(main->setting.receive.polls, kt_tacocat_interval_poll_d);
+
+        if (main->program.signal_received) {
+          main->setting.status_receive = F_status_set_error(F_interrupt);
+
+          return 0;
+        }
+
+        // @todo handle errors
+
+      } while (F_status_is_error_not(main->setting.status_receive));
+    }
+
+    kt_tacocat_process_socket_set_disconnect(main, &main->setting.receive);
+
+    kt_tacocat_process_socket_set_error_handle(main, main->setting.receive, &main->setting.status_receive);
+
+    if (F_status_is_error_not(main->setting.status_receive)) {
+      main->setting.status_receive = F_none;
+    }
+
+    return 0;
+  }
+#endif // _di_kt_tacocat_receive_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sources/c/tacocat/main/receive.h b/sources/c/tacocat/main/receive.h
new file mode 100644 (file)
index 0000000..702a93f
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ */
+#ifndef _kt_tacocat_receive_h
+#define _kt_tacocat_receive_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the receive operation for the receive sockets.
+ *
+ * @param main
+ *   The main program and settings data.
+ *
+ *   Must be of type kt_tacocat_main_t.
+ *
+ *   This alters main.setting.state.status:
+ *     F_none on success.
+ *     F_child on child process exiting.
+ *
+ * @return
+ *   0, always.
+ */
+#ifndef _di_kt_tacocat_receive_
+  extern void * kt_tacocat_receive(void * const main);
+#endif // _di_kt_tacocat_receive_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_receive_h
diff --git a/sources/c/tacocat/main/send.c b/sources/c/tacocat/main/send.c
new file mode 100644 (file)
index 0000000..d7efc05
--- /dev/null
@@ -0,0 +1,36 @@
+#include "tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_tacocat_send_
+  void * kt_tacocat_send(void * const void_main) {
+
+    f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+
+    if (!void_main) return 0;
+
+    kt_tacocat_main_t * const main = (kt_tacocat_main_t *) void_main;
+
+    kt_tacocat_process_socket_set_send(main);
+
+    if (F_status_is_error_not(main->setting.status_send)) {
+      // @todo
+    }
+
+    kt_tacocat_process_socket_set_disconnect(main, &main->setting.send);
+
+    kt_tacocat_process_socket_set_error_handle(main, main->setting.send, &main->setting.status_send);
+
+    if (F_status_is_error_not(main->setting.status_send)) {
+      main->setting.status_send = F_none;
+    }
+
+    return 0;
+  }
+#endif // _di_kt_tacocat_send_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sources/c/tacocat/main/send.h b/sources/c/tacocat/main/send.h
new file mode 100644 (file)
index 0000000..55c4260
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ */
+#ifndef _kt_tacocat_send_h
+#define _kt_tacocat_send_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the send operation for the send sockets.
+ *
+ * @param main
+ *   The main program and settings data.
+ *
+ *   Must be of type kt_tacocat_main_t.
+ *
+ *   This alters main.setting.state.status:
+ *     F_none on success.
+ *     F_child on child process exiting.
+ *
+ * @return
+ *   0, always.
+ */
+#ifndef _di_kt_tacocat_send_
+  extern void * kt_tacocat_send(void * const main);
+#endif // _di_kt_tacocat_send_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_send_h
index 46a47d606587d8875601fb7b3854d20eb2c1c5f6..026691aa5efbe65abb841b1f1b3fee94904ac632 100644 (file)
@@ -52,9 +52,9 @@ extern "C" {
     f_signal_set_add(F_signal_termination, &main->program.signal.set);
 
     if (main->program.signal.id == -1) {
-      main->setting.status_thread = f_signal_open(&main->program.signal);
+      main->setting.status_signal = f_signal_open(&main->program.signal);
 
-      if (F_status_is_error(main->setting.status_thread)) {
+      if (F_status_is_error(main->setting.status_signal)) {
         main->program.signal_received = F_signal_abort;
 
         return;
@@ -64,9 +64,9 @@ extern "C" {
     do {
       memset(&information, 0, sizeof(siginfo_t));
 
-      main->setting.status_thread = f_signal_wait(&main->program.signal.set, &information);
+      main->setting.status_signal = f_signal_wait(&main->program.signal.set, &information);
 
-      if (F_status_is_error(main->setting.status_thread) && F_status_set_fine(main->setting.status_thread) != F_interrupt) {
+      if (F_status_is_error(main->setting.status_signal) && F_status_set_fine(main->setting.status_signal) != F_interrupt) {
         if (++failsafe >= kt_tacocat_signal_check_failsafe_d) break;
       }
 
@@ -83,13 +83,13 @@ extern "C" {
       }
 
       failsafe = 0;
-      main->setting.status_thread = F_none;
+      main->setting.status_signal = F_none;
 
     } while (!main->program.signal_received);
 
     f_signal_close(&main->program.signal);
 
-    if (F_status_is_error(main->setting.status_thread)) {
+    if (F_status_is_error(main->setting.status_signal)) {
       main->program.signal_received = F_signal_abort;
     }
   }
index f0c837c606fee3802d3a149cc6b52a50ec824615..e7f066a6a8d56f4d0725c0097402da5c1d775457 100644 (file)
@@ -57,6 +57,8 @@
 #include <program/kevux/tools/tacocat/main/print/verbose.h>
 #include <program/kevux/tools/tacocat/main/print/warning.h>
 #include <program/kevux/tools/tacocat/main/process.h>
+#include <program/kevux/tools/tacocat/main/receive.h>
+#include <program/kevux/tools/tacocat/main/send.h>
 #include <program/kevux/tools/tacocat/main/signal.h>
 #include <program/kevux/tools/tacocat/main/thread.h>