]> Kevux Git Server - kevux-tools/commitdiff
Progress: Further work in TacocaT.
authorKevin Day <kevin@kevux.org>
Fri, 7 Jul 2023 03:42:12 +0000 (22:42 -0500)
committerKevin Day <kevin@kevux.org>
Fri, 7 Jul 2023 03:46:29 +0000 (22:46 -0500)
Add socket and status arrays for receiving and sending.

Start calling the socket setup and tear down code.

Have the disconnect on exit disconnect cleanly unless an interrupt is called.

sources/c/tacocat/main/common.c
sources/c/tacocat/main/common/print.c
sources/c/tacocat/main/common/print.h
sources/c/tacocat/main/common/type.c
sources/c/tacocat/main/common/type.h
sources/c/tacocat/main/print/error.c
sources/c/tacocat/main/print/error.h
sources/c/tacocat/main/process.c

index e8f5f133dc378e66c7ff4578dd833ec8021a56c9..cd652e1d732514ed73927a624151b5372bef370f 100644 (file)
@@ -177,6 +177,16 @@ extern "C" {
       &main->setting.file_sends,
     };
 
+    f_sockets_t * const sockets[] = {
+      &main->setting.socket_receives,
+      &main->setting.socket_sends,
+    };
+
+    f_statuss_t * const statuss[] = {
+      &main->setting.status_receives,
+      &main->setting.status_sends,
+    };
+
     const bool const is_receive[] = {
       F_true,
       F_false,
@@ -219,6 +229,14 @@ extern "C" {
 
         macro_setting_load_handle_send_receive_error_continue_basic(f_files_increase_by);
 
+        main->setting.state.status = f_sockets_increase_by(main->program.parameters.array[parameters[i]].values.used / 2, sockets[i]);
+
+        macro_setting_load_handle_send_receive_error_continue_basic(f_sockets_increase_by);
+
+        main->setting.state.status = f_statuss_increase_by(main->program.parameters.array[parameters[i]].values.used / 2, statuss[i]);
+
+        macro_setting_load_handle_send_receive_error_continue_basic(f_statuss_increase_by);
+
         for (j = 0; j < main->program.parameters.array[parameters[i]].values.used; j += 2) {
 
           // First parameter value represents the network address or the socket file path.
index e59f9884a5eaad1a544cd4403c9aa5c8950da113..01e38a28333b5412fffb99f9054bad2d9bd76799 100644 (file)
@@ -10,6 +10,12 @@ extern "C" {
     "f_file_open",
     "f_files_increase_by",
     "f_network_from_ip_name",
+    "f_socket_close",
+    "f_socket_create",
+    "f_socket_disconnect",
+    "f_socket_listen",
+    "f_sockets_increase_by",
+    "f_statuss_increase_by",
     "f_string_append_nulless",
     "f_string_dynamic_append_nulless",
     "f_string_dynamic_increase_by",
index e61dbb6b1a989c451d19694579a16eb436d8616e..1d420387e5e9f2e766d1368c032957c4b30c9cd3 100644 (file)
@@ -43,6 +43,12 @@ extern "C" {
     kt_tacocat_f_f_file_open_e,
     kt_tacocat_f_f_files_increase_by_e,
     kt_tacocat_f_f_network_from_ip_name_e,
+    kt_tacocat_f_f_socket_close_e,
+    kt_tacocat_f_f_socket_create_e,
+    kt_tacocat_f_f_socket_disconnect_e,
+    kt_tacocat_f_f_socket_listen_e,
+    kt_tacocat_f_f_sockets_increase_by_e,
+    kt_tacocat_f_f_statuss_increase_by_e,
     kt_tacocat_f_f_string_append_nulless_e,
     kt_tacocat_f_f_string_dynamic_append_nulless_e,
     kt_tacocat_f_f_string_dynamic_increase_by_e,
index 126f4e093f79b675ff92f64219255e24b5e99054..5c13fb7f68612dc105529d087e5e57ca82f12741 100644 (file)
@@ -10,12 +10,12 @@ extern "C" {
     if (!main) return;
 
     fll_program_data_delete(&main->program);
-    kt_tacocat_setting_delete(&main->setting);
+    kt_tacocat_setting_delete(main->program, &main->setting);
   }
 #endif // _di_kt_tacocat_main_delete_
 
 #ifndef _di_kt_tacocat_setting_delete_
-  f_status_t kt_tacocat_setting_delete(kt_tacocat_setting_t * const setting) {
+  f_status_t kt_tacocat_setting_delete(const fll_program_data_t program, kt_tacocat_setting_t * const setting) {
 
     if (!setting) return F_status_set_error(F_parameter);
 
@@ -29,16 +29,28 @@ extern "C" {
       f_file_close(&setting->file_sends.array[i]);
     } // for
 
+    for (; i < setting->socket_receives.used ; ++i) {
+      f_socket_disconnect(&setting->socket_receives.array[i], program.signal_received ? f_socket_close_fast_e : f_socket_close_read_write_e);
+    } // for
+
+    for (; i < setting->socket_sends.used ; ++i) {
+      f_socket_disconnect(&setting->socket_sends.array[i], program.signal_received ? f_socket_close_fast_e : f_socket_close_read_write_e);
+    } // for
+
     f_files_resize(0, &setting->file_receives);
     f_files_resize(0, &setting->file_sends);
 
     f_sockets_resize(0, &setting->socket_receives);
     f_sockets_resize(0, &setting->socket_sends);
 
-    f_string_dynamic_resize(0, &setting->buffer);
+    f_statuss_resize(0, &setting->status_receives);
+    f_statuss_resize(0, &setting->status_sends);
+
     f_string_dynamics_resize(0, &setting->receives);
     f_string_dynamics_resize(0, &setting->sends);
 
+    f_string_dynamic_resize(0, &setting->buffer);
+
     return F_none;
   }
 #endif // _di_kt_tacocat_setting_delete_
index 0461bfe23ad74fa578b7b125157c5a471c4d1fd9..a77a32ac4c43fc515b34e1fd2a570d08c054f27b 100644 (file)
@@ -30,16 +30,19 @@ extern "C" {
  * status_thread: A status used eclusively by the threaded signal handler.
  * state:         The state data used when processing data.
  *
- * file_receives: An array of input files.
- * file_sends:    An array of output files.
+ * file_receives: An array of files for receiving.
+ * file_sends:    An array of files for sending.
  *
  * socket_receives: An array of the network sockets for receiving.
  * socket_sends:    An array of the network sockets for sending.
  *
- * buffer:   A string buffer used for caching purposes.
+ * status_receives: An array of statuses for receiving.
+ * status_sends:    An array of statuses for sending.
  *
  * receives: An array of buffers for receiving data receive clients.
  * sends:    An array of buffers for sending data send clients.
+ *
+ * buffer:   A string buffer used for caching purposes.
  */
 #ifndef _di_kt_tacocat_setting_t_
   typedef struct {
@@ -57,10 +60,13 @@ extern "C" {
     f_sockets_t socket_receives;
     f_sockets_t socket_sends;
 
-    f_string_dynamic_t buffer;
+    f_statuss_t status_receives;
+    f_statuss_t status_sends;
 
     f_string_dynamics_t receives;
     f_string_dynamics_t sends;
+
+    f_string_dynamic_t buffer;
   } kt_tacocat_setting_t;
 
   #define kt_tacocat_setting_t_initialize \
@@ -74,9 +80,11 @@ extern "C" {
       f_files_t_initialize, \
       f_sockets_t_initialize, \
       f_sockets_t_initialize, \
-      f_string_dynamic_t_initialize, \
+      f_statuss_t_initialize, \
+      f_statuss_t_initialize, \
       f_string_dynamics_t_initialize, \
       f_string_dynamics_t_initialize, \
+      f_string_dynamic_t_initialize, \
     }
 #endif // _di_kt_tacocat_setting_t_
 
@@ -133,6 +141,8 @@ extern "C" {
 /**
  * Delete the program main setting data.
  *
+ * @param program
+ *   The main program data.
  * @param setting
  *   The program main setting data.
  *
@@ -144,7 +154,7 @@ extern "C" {
  *   F_parameter (with error bit) if a parameter is invalid.
  */
 #ifndef _di_kt_tacocat_setting_delete_
-  extern f_status_t kt_tacocat_setting_delete(kt_tacocat_setting_t * const setting);
+  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_
 
 #ifdef __cplusplus
index e1ff09d1e022b4c8e5eada5184c3da0c39c6cb5e..f8179a36b9dc9410eecb0aab90d09b2ae853274a 100644 (file)
@@ -52,6 +52,32 @@ extern "C" {
   }
 #endif // _di_kt_tacocat_print_error_parameter_value_resolve_unknown_
 
+#ifndef _di_kt_tacocat_print_error_setting_socket_lengths_must_match_
+  f_status_t kt_tacocat_print_error_setting_socket_lengths_must_match(fl_print_t * const print, const f_string_dynamic_t name, const f_number_unsigned_t names, const f_number_unsigned_t files, const f_number_unsigned_t sockets, const f_number_unsigned_t statuss) {
+
+    if (!print || !print->custom) return F_status_set_error(F_output_not);
+    if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
+
+    f_file_stream_lock(print->to);
+
+    fl_print_format("%[%QThe lengths of all%] ", print->to, print->set->error, print->prefix, print->set->error);
+    fl_print_format("%[%Q%]", print->to, print->set->notable, name, print->set->notable);
+    fl_print_format(" %[arrays do not have the same length, name array length is '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format("%[%ul%]", print->to, print->set->notable, names, print->set->notable);
+    fl_print_format("%', the file array length is '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format("%[%ul%]", print->to, print->set->notable, files, print->set->notable);
+    fl_print_format(" %[', the socket array length is '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format("%[%ul%]", print->to, print->set->notable, sockets, print->set->notable);
+    fl_print_format(" %[', and the status array length is '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+    fl_print_format("%[%ul%]", print->to, print->set->notable, statuss, print->set->notable);
+    fl_print_format(" %['.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
+
+    f_file_stream_unlock(print->to);
+
+    return F_none;
+  }
+#endif // _di_kt_tacocat_print_error_setting_socket_lengths_must_match_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 173a22476d8f4691f415d147b05f5a36457e78cd..274bdf3a44afc6c3cc94fc1aa460153549c16f92 100644 (file)
@@ -87,6 +87,36 @@ extern "C" {
   extern f_status_t kt_tacocat_print_error_parameter_value_resolve_unknown(fl_print_t * const print, const f_string_dynamic_t unknown);
 #endif // _di_kt_tacocat_print_error_parameter_value_resolve_unknown_
 
+/**
+ * Print error message for when an the different socket relating structure arrays do not have the same length.
+ *
+ * @param print
+ *   The output structure to print to.
+ *
+ *   This does not alter print.custom.setting.state.status.
+ * @param name
+ *   The name of the set of arrays that must have the same length.
+ * @param names
+ *   The length of the names array.
+ * @param files
+ *   The length of the files array.
+ * @param sockets
+ *   The length of the sockets array.
+ * @param statuss
+ *   The length of the statuss array.
+ *
+ * @return
+ *   F_none on success.
+ *   F_output_not on success, but no printing is performed.
+ *
+ *   F_output_not (with error bit) if setting is NULL.
+ *
+ * @see fll_error_file_print()
+ */
+#ifndef _di_kt_tacocat_print_error_setting_socket_lengths_must_match_
+  extern f_status_t kt_tacocat_print_error_setting_socket_lengths_must_match(fl_print_t * const print, const f_string_dynamic_t name, const f_number_unsigned_t names, const f_number_unsigned_t files, const f_number_unsigned_t sockets, const f_number_unsigned_t statuss);
+#endif // _di_kt_tacocat_print_error_setting_socket_lengths_must_match_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 2ff13ddad2930a3cf553f1260eb812921e702367..3469a2dee6ce8ff300b0299cb65f24331d4f4f8d 100644 (file)
@@ -9,15 +9,142 @@ extern "C" {
 
     if (!main) return;
 
+    if (main->setting.socket_receives.used != main->setting.file_receives.used && main->setting.socket_receives.used != main->setting.receives.used && main->setting.socket_receives.used != main->setting.status_receives.used) {
+      main->setting.state.status = F_status_set_error(F_parameter);
+
+      kt_tacocat_print_error_setting_socket_lengths_must_match(&main->program.error, kt_tacocat_long_receive_s, main->setting.receives.used, main->setting.file_receives.used, main->setting.socket_receives.used, main->setting.status_receives.used);
+
+      return;
+    }
+
+    if (main->setting.socket_sends.used != main->setting.file_sends.used && main->setting.socket_sends.used != main->setting.sends.used && main->setting.socket_sends.used != main->setting.status_sends.used) {
+      main->setting.state.status = F_status_set_error(F_parameter);
+
+      kt_tacocat_print_error_setting_socket_lengths_must_match(&main->program.error, kt_tacocat_long_send_s, main->setting.sends.used, main->setting.file_sends.used, main->setting.socket_sends.used, main->setting.status_sends.used);
+
+      return;
+    }
+
     f_number_unsigned_t i = 0;
 
+    // @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.
+
+    // Create socket and connect to socket (bind / listen).
+    for (; i < main->setting.socket_receives.used; ++i) {
+
+      if (kt_tacocat_signal_check(main)) return;
+
+      // @todo check to see if connection is one of "local", "inet" (ipv4), or "inet6" (ipv6) and configure socket appropriately.
+
+      main->setting.status_receives.array[i] = f_socket_create(&main->setting.socket_receives.array[i]);
+
+      if (F_status_is_error(main->setting.status_receives.array[i])) {
+        main->setting.state.status = main->setting.status_receives.array[i];
+
+        kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_socket_create));
+
+        continue;
+      }
+
+      main->setting.status_receives.array[i] = f_socket_listen(&main->setting.socket_receives.array[i], 100); // @todo setup a max back log define rather than hardcode 100 here (and 100 is arbitrarily chosen).
+
+      if (F_status_is_error(main->setting.status_receives.array[i])) {
+        main->setting.state.status = main->setting.status_receives.array[i];
+
+        kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_socket_listen));
+
+        continue;
+      }
+    } // for
+
+    for (i = 0; i < main->setting.socket_sends.used; ++i) {
+
+      if (kt_tacocat_signal_check(main)) return;
+
+      // @todo check to see if connection is one of "local", "inet" (ipv4), or "inet6" (ipv6) and configure socket appropriately.
+
+      main->setting.status_sends.array[i] = f_socket_create(&main->setting.socket_sends.array[i]);
+
+      if (F_status_is_error(main->setting.status_sends.array[i])) {
+        main->setting.state.status = main->setting.status_sends.array[i];
+
+        kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_socket_create));
+
+        continue;
+      }
+
+      // @todo f_socket_bind().
+    } // for
+
+    // 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.
 
-    main->setting.state.status = F_none;
+    // Disconnect.
+    for (; i < main->setting.socket_receives.used; ++i) {
+
+      if (kt_tacocat_signal_check(main)) return;
+
+      main->setting.status_receives.array[i] = f_socket_disconnect(&main->setting.socket_receives.array[i], f_socket_close_read_write_e);
+
+      if (F_status_is_error(main->setting.status_receives.array[i])) {
+        main->setting.state.status = main->setting.status_receives.array[i];
+
+        kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_socket_disconnect));
+      }
+    } // for
+
+    for (i = 0; i < main->setting.socket_sends.used; ++i) {
+
+      if (kt_tacocat_signal_check(main)) return;
+
+      main->setting.status_sends.array[i] = f_socket_disconnect(&main->setting.socket_sends.array[i], f_socket_close_read_write_e);
+
+      if (F_status_is_error(main->setting.status_sends.array[i])) {
+        main->setting.state.status = main->setting.status_sends.array[i];
+
+        kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_socket_disconnect));
+      }
+    } // for
+
+    // Handle returning errors.
+    if (F_status_is_error_not(main->setting.state.status)) {
+      main->setting.state.status = F_none;
+
+      for (i = 0; i < main->setting.socket_receives.used; ++i) {
+
+        if (kt_tacocat_signal_check(main)) return;
+
+        if (F_status_is_error(main->setting.status_receives.array[i])) {
+          main->setting.state.status = main->setting.status_receives.array[i];
+        }
+      } // for
+
+      for (i = 0; i < main->setting.socket_sends.used; ++i) {
+
+        if (kt_tacocat_signal_check(main)) return;
+
+        if (F_status_is_error(main->setting.status_sends.array[i])) {
+          main->setting.state.status = main->setting.status_sends.array[i];
+        }
+      } // for
+    }
   }
 #endif // _di_kt_tacocat_process_main_