]> Kevux Git Server - kevux-tools/commitdiff
Progress: Further work in TacocaT, updating "salt" and "time" packet headers.
authorKevin Day <kevin@kevux.org>
Wed, 13 Mar 2024 03:20:10 +0000 (22:20 -0500)
committerKevin Day <kevin@kevux.org>
Wed, 13 Mar 2024 03:20:10 +0000 (22:20 -0500)
The "salt" header is now in the FLL project.
Remove the "salt" string definition from this project.

The packet send now utilizes the "time" header via the standard UTC time.
This is for informative purposes rather than for any accurancy.
Which means that the lack of microseconds or nanoseconds is acceptable.

sources/c/tacocat/main/common/define.h
sources/c/tacocat/main/common/string.c
sources/c/tacocat/main/common/string.h
sources/c/tacocat/main/common/type.c
sources/c/tacocat/main/common/type.h
sources/c/tacocat/main/packet.c
sources/c/tacocat/main/process.c
sources/c/tacocat/main/send.c
sources/c/tacocat/main/send.h

index e060d7ec5f05ae0d35ec12ebfb18a2b6f33fcb6b..140d946cdbd964c59292296e55cd7aeb7ebfd9b3 100644 (file)
@@ -37,6 +37,7 @@ extern "C" {
  *   - poll_fast: The time in milliseconds to poll for before returning fo fast polls, such as when there is an active process (this is the amount of time poll() blocks).
  *
  * kt_tacocat_max_*_d:
+ *   - asctime:  The max string length supported for the string returned by asctime().
  *   - backlog:  The max backlog in bytes size to use.
  *   - buffer:   The max buffer in bytes size to use when receiving packets.
  *   - maintain: The max size in bytes to maintain a particular buffer.
@@ -76,11 +77,12 @@ extern "C" {
   #define kt_tacocat_interval_poll_d      1400 // 1.4 second.
   #define kt_tacocat_interval_poll_fast_d 5    // 0.005 second.
 
+  #define kt_tacocat_max_asctime_d  0xff
   #define kt_tacocat_max_backlog_d  0x400
   #define kt_tacocat_max_buffer_d   0x10000000 // 0x10^0x5 * 0x100 (Which is 256 Megabytes (0x10^0x5 where the base unit is 16 rather than 10 or 2 (maybe call this xytes? Megaxytes?)).
   #define kt_tacocat_max_maintain_d 0x100000   // 0x10^5 (Which is 1 Megabyte in base 16 (1 Megaxyte (MX)).
 
-  #define kt_tacocat_packet_headers_d   0x8
+  #define kt_tacocat_packet_headers_d   0x9
   #define kt_tacocat_packet_id_length_d 0x20
   #define kt_tacocat_packet_minimum_d   0x11
   #define kt_tacocat_packet_peek_d      0x40
index bee3a1a5fd312fee61a7bc511b0b0e5d11e592dd..4b17022daaa67f741676a2b5934f6e6152b1ea5b 100644 (file)
@@ -29,7 +29,6 @@ extern "C" {
   const f_string_static_t kt_tacocat_next_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_next_s, 0, KT_TACOCAT_next_s_length);
   const f_string_static_t kt_tacocat_receive_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_receive_s, 0, KT_TACOCAT_receive_s_length);
   const f_string_static_t kt_tacocat_resend_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_resend_s, 0, KT_TACOCAT_resend_s_length);
-  const f_string_static_t kt_tacocat_salt_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_salt_s, 0, KT_TACOCAT_salt_s_length);
   const f_string_static_t kt_tacocat_send_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_send_s, 0, KT_TACOCAT_send_s_length);
   const f_string_static_t kt_tacocat_send_build_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_send_build_s, 0, KT_TACOCAT_send_build_s_length);
   const f_string_static_t kt_tacocat_send_combine_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_send_combine_s, 0, KT_TACOCAT_send_combine_s_length);
@@ -41,6 +40,7 @@ extern "C" {
   const f_string_static_t kt_tacocat_send_size_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_send_size_s, 0, KT_TACOCAT_send_size_s_length);
   const f_string_static_t kt_tacocat_socket_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_socket_s, 0, KT_TACOCAT_socket_s_length);
   const f_string_static_t kt_tacocat_tacocat_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_tacocat_s, 0, KT_TACOCAT_tacocat_s_length);
+  const f_string_static_t kt_tacocat_time_utc_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_time_utc_s, 0, KT_TACOCAT_time_utc_s_length);
   const f_string_static_t kt_tacocat_two_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_two_s, 0, KT_TACOCAT_two_s_length);
 #endif // _di_kt_tacocat_s_
 
index 0033efa947ff530bbd349baac8457b601bf0fc4a..82157041c836b39dfc18406f9acbfe81bfdfb7e0 100644 (file)
@@ -83,7 +83,6 @@ extern "C" {
   #define KT_TACOCAT_next_s               "next"
   #define KT_TACOCAT_receive_s            "receive"
   #define KT_TACOCAT_resend_s             "resend"
-  #define KT_TACOCAT_salt_s               "salt"
   #define KT_TACOCAT_send_s               "send"
   #define KT_TACOCAT_send_build_s         "send build"
   #define KT_TACOCAT_send_combine_s       "send combine"
@@ -95,6 +94,7 @@ extern "C" {
   #define KT_TACOCAT_send_size_s          "send size"
   #define KT_TACOCAT_socket_s             "socket"
   #define KT_TACOCAT_tacocat_s            "tacocat"
+  #define KT_TACOCAT_time_utc_s           " UTC"
   #define KT_TACOCAT_two_s                "two"
 
   #define KT_TACOCAT_abort_s_length              5
@@ -108,7 +108,6 @@ extern "C" {
   #define KT_TACOCAT_next_s_length               4
   #define KT_TACOCAT_receive_s_length            7
   #define KT_TACOCAT_resend_s_length             6
-  #define KT_TACOCAT_salt_s_length               4
   #define KT_TACOCAT_send_s_length               4
   #define KT_TACOCAT_send_build_s_length         19
   #define KT_TACOCAT_send_combine_s_length       12
@@ -120,6 +119,7 @@ extern "C" {
   #define KT_TACOCAT_send_size_s_length          9
   #define KT_TACOCAT_socket_s_length             6
   #define KT_TACOCAT_tacocat_s_length            7
+  #define KT_TACOCAT_time_utc_s_length           4
   #define KT_TACOCAT_two_s_length                3
 
   extern const f_string_static_t kt_tacocat_abort_s;
@@ -133,7 +133,6 @@ extern "C" {
   extern const f_string_static_t kt_tacocat_next_s;
   extern const f_string_static_t kt_tacocat_receive_s;
   extern const f_string_static_t kt_tacocat_resend_s;
-  extern const f_string_static_t kt_tacocat_salt_s;
   extern const f_string_static_t kt_tacocat_send_s;
   extern const f_string_static_t kt_tacocat_send_build_s;
   extern const f_string_static_t kt_tacocat_send_combine_s;
@@ -145,6 +144,7 @@ extern "C" {
   extern const f_string_static_t kt_tacocat_send_size_s;
   extern const f_string_static_t kt_tacocat_socket_s;
   extern const f_string_static_t kt_tacocat_tacocat_s;
+  extern const f_string_static_t kt_tacocat_time_utc_s;
   extern const f_string_static_t kt_tacocat_two_s;
 #endif // _di_kt_tacocat_s_
 
index b72d1dcde8a451dfae318a9f5b75948b09ce7858..516e20c2de90fb438e74d0b9ad7d0de71b61d7fe 100644 (file)
@@ -150,6 +150,10 @@ extern "C" {
           f_memory_array_resize(0, sizeof(f_char_t), (void **) &array[i].network.string, &array[i].network.used, &array[i].network.size);
         }
 
+        if (array[i].time.size) {
+          f_memory_array_resize(0, sizeof(f_char_t), (void **) &array[i].time.string, &array[i].time.used, &array[i].time.size);
+        }
+
         if (array[i].abstruses.size) {
           f_memory_arrays_resize(0, sizeof(f_abstruse_map_t), (void **) &array[i].abstruses.array, &array[i].abstruses.used, &array[i].abstruses.size, &f_abstruse_maps_delete_callback);
         }
index f910f54406f2a4e47deb50f1423499192a52f947..e21397c451ad231b7b75e124818402710c5ea77c 100644 (file)
@@ -59,6 +59,7 @@ extern "C" {
  * header:      A buffer used for the header part and possibly the reset of a packet, except for the actual payload.
  * name:        A file name for reading from or writing to.
  * network:     A network name for the socket.
+ * time:        A representation of time added for informative purposes to the packet (in a human friendly format).
  * packet:      The simple packet range representing the parts of the packet for use during processing.
  * write_state: State data for the packet write operation.
  *
@@ -108,6 +109,7 @@ extern "C" {
     f_string_dynamic_t id;
     f_string_dynamic_t name;
     f_string_dynamic_t network;
+    f_string_dynamic_t time;
     f_fss_simple_packet_range_t packet;
     fl_fss_payload_header_state_t write_state;
 
@@ -150,6 +152,7 @@ extern "C" {
       f_string_dynamic_t_initialize, \
       f_string_dynamic_t_initialize, \
       f_string_dynamic_t_initialize, \
+      f_string_dynamic_t_initialize, \
       f_fss_simple_packet_range_t_initialize, \
       fl_fss_payload_header_state_t_initialize, \
       f_abstruse_maps_t_initialize, \
@@ -192,6 +195,7 @@ extern "C" {
       f_string_dynamic_t_initialize, \
       f_string_dynamic_t_initialize, \
       f_string_dynamic_t_initialize, \
+      f_string_dynamic_t_initialize, \
       f_fss_simple_packet_range_t_initialize, \
       fl_fss_payload_header_state_t_initialize, \
       f_abstruse_maps_t_initialize, \
@@ -234,6 +238,7 @@ extern "C" {
       f_string_dynamic_t_initialize, \
       f_string_dynamic_t_initialize, \
       f_string_dynamic_t_initialize, \
+      f_string_dynamic_t_initialize, \
       f_fss_simple_packet_range_t_initialize, \
       write_state, \
       f_abstruse_maps_t_initialize, \
index 2dce22c99e180396ab9905eae6df56dc104bb261..d52180c72acddbc7755cb77ba89cdb031669cc2e 100644 (file)
@@ -98,120 +98,40 @@ extern "C" {
 
     f_number_unsigned_t i = 0;
 
-    for (; i < set->objects_header.used; ++i) {
-
-      // Index 0 is the status.
-      if (f_compare_dynamic_partial_string(f_fss_payload_object_status_s.string, set->buffer, f_fss_payload_object_status_s.used, set->objects_header.array[i]) == F_equal_to) {
-
-        // Require Content to exist.
-        if (!set->contents_header.array[i].used) {
-          set->abstruses.array[0].value.type = f_abstruse_none_e;
-
-          continue;
-        }
-
-        set->abstruses.array[0].value.type = f_abstruse_range_e;
-        set->abstruses.array[0].value.is.a_range = set->contents_header.array[i].array[0];
-      }
-
-      // Index 1 is the type.
-      else if (f_compare_dynamic_partial_string(f_fss_payload_object_type_s.string, set->buffer, f_fss_payload_object_type_s.used, set->objects_header.array[i]) == F_equal_to) {
-
-        // Require Content to exist.
-        if (!set->contents_header.array[i].used) {
-         set->abstruses.array[1].value.type = f_abstruse_none_e;
-
-          continue;
-        }
-
-        set->abstruses.array[1].value.type = f_abstruse_range_e;
-        set->abstruses.array[1].value.is.a_range = set->contents_header.array[i].array[0];
-      }
-
-      // Index 2 is the length.
-      else if (f_compare_dynamic_partial_string(f_fss_payload_object_length_s.string, set->buffer, f_fss_payload_object_length_s.used, set->objects_header.array[i]) == F_equal_to) {
-
-        // Require Content to exist.
-        if (!set->contents_header.array[i].used) {
-         set->abstruses.array[2].value.type = f_abstruse_none_e;
-
-          continue;
-        }
-
-        set->abstruses.array[2].value.type = f_abstruse_range_e;
-        set->abstruses.array[2].value.is.a_range = set->contents_header.array[i].array[0];
-      }
-
-      // Index 3 is the part.
-      else if (f_compare_dynamic_partial_string(f_fss_payload_object_part_s.string, set->buffer, f_fss_payload_object_part_s.used, set->objects_header.array[i]) == F_equal_to) {
-
-        // Require Content to exist.
-        if (!set->contents_header.array[i].used) {
-         set->abstruses.array[3].value.type = f_abstruse_none_e;
-
-          continue;
-        }
-
-        set->abstruses.array[3].value.type = f_abstruse_range_e;
-        set->abstruses.array[3].value.is.a_range = set->contents_header.array[i].array[0];
-      }
-
-      // Index 4 is the total number of packets (based on block size).
-      else if (f_compare_dynamic_partial_string(f_fss_payload_object_total_s.string, set->buffer, f_fss_payload_object_total_s.used, set->objects_header.array[i]) == F_equal_to) {
-
-        // Require Content to exist.
-        if (!set->contents_header.array[i].used) {
-         set->abstruses.array[4].value.type = f_abstruse_none_e;
-
-          continue;
-        }
-
-        set->abstruses.array[4].value.type = f_abstruse_range_e;
-        set->abstruses.array[4].value.is.a_range = set->contents_header.array[i].array[0];
-      }
-
-      // Index 5 is the name (file name).
-      else if (f_compare_dynamic_partial_string(f_fss_payload_object_name_s.string, set->buffer, f_fss_payload_object_name_s.used, set->objects_header.array[i]) == F_equal_to) {
-
-        // Require Content to exist.
-        if (!set->contents_header.array[i].used) {
-         set->abstruses.array[5].value.type = f_abstruse_none_e;
-
-          continue;
-        }
-
-        set->abstruses.array[5].value.type = f_abstruse_range_e;
-        set->abstruses.array[5].value.is.a_range = set->contents_header.array[i].array[0];
-      }
+    {
+      uint8_t j = 0;
 
-      // Index 6 is the salt.
-      else if (f_compare_dynamic_partial_string(kt_tacocat_salt_s.string, set->buffer, kt_tacocat_salt_s.used, set->objects_header.array[i]) == F_equal_to) {
+      f_string_static_t headers[] = {
+        f_fss_payload_object_status_s,
+        f_fss_payload_object_type_s,
+        f_fss_payload_object_length_s,
+        f_fss_payload_object_part_s,
+        f_fss_payload_object_total_s,
+        f_fss_payload_object_name_s,
+        f_fss_payload_object_salt_s,
+        f_fss_payload_object_id_s,
+        f_fss_payload_object_time_s,
+      };
 
-        // Require Content to exist.
-        if (!set->contents_header.array[i].used) {
-          set->abstruses.array[6].value.type = f_abstruse_none_e;
+      for (; i < set->objects_header.used; ++i) {
 
-          continue;
-        }
+        for (j = 0; j < 9; ++j) {
 
-        set->abstruses.array[6].value.type = f_abstruse_range_e;
-        set->abstruses.array[6].value.is.a_range = set->contents_header.array[i].array[0];
-      }
+          if (f_compare_dynamic_partial_string(headers[j].string, set->buffer, headers[j].used, set->objects_header.array[i]) == F_equal_to) {
 
-      // Index 7 is the transaction id.
-      else if (f_compare_dynamic_partial_string(f_fss_payload_object_id_s.string, set->buffer, f_fss_payload_object_id_s.used, set->objects_header.array[i]) == F_equal_to) {
+            // Require Content to exist.
+            if (!set->contents_header.array[i].used) {
+              set->abstruses.array[j].value.type = f_abstruse_none_e;
 
-        // Require Content to exist.
-        if (!set->contents_header.array[i].used) {
-          set->abstruses.array[7].value.type = f_abstruse_none_e;
+              break;
+            }
 
-          continue;
-        }
-
-        set->abstruses.array[7].value.type = f_abstruse_range_e;
-        set->abstruses.array[7].value.is.a_range = set->contents_header.array[i].array[0];
-      }
-    } // for
+            set->abstruses.array[j].value.type = f_abstruse_range_e;
+            set->abstruses.array[j].value.is.a_range = set->contents_header.array[i].array[0];
+          }
+        } // for
+      } // for
+    }
 
     // Convert the status code.
     if (set->abstruses.array[0].value.type) {
index c5d3a59226b077f703bee1ef890d6875d0d44911..f496b525a3dfcc883d5cef0666eb4157266020ba 100644 (file)
@@ -64,59 +64,65 @@ extern "C" {
 #ifndef _di_kt_tacocat_process_abstruse_initialize_
   void kt_tacocat_process_abstruse_initialize(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
 
-      set->status = f_memory_array_increase_by(kt_tacocat_packet_headers_d, sizeof(f_abstruse_map_t), (void **) &set->abstruses.array, &set->abstruses.used, &set->abstruses.size);
-      if (F_status_is_error(set->status)) return;
-
-      // Index 0 is the status.
-      set->abstruses.array[0].key = f_fss_payload_object_status_s;
-      set->abstruses.array[0].value.type = f_abstruse_dynamic_e;
-      set->abstruses.array[0].value.is.a_dynamic = f_status_okay_s;
-
-      // Index 1 is the type.
-      set->abstruses.array[1].key = f_fss_payload_object_type_s;
-      set->abstruses.array[1].value.type = f_abstruse_dynamic_e;
-      set->abstruses.array[1].value.is.a_dynamic = f_file_type_name_file_s;
-
-      // Index 2 is the length.
-      set->abstruses.array[2].key = f_fss_payload_object_length_s;
-      set->abstruses.array[2].value.type = f_abstruse_unsigned_e;
-      set->abstruses.array[2].value.is.a_unsigned = 0;
-
-      // Index 3 is the part.
-      set->abstruses.array[3].key = f_fss_payload_object_part_s;
-      set->abstruses.array[3].value.type = f_abstruse_unsigned_e;
-      set->abstruses.array[3].value.is.a_unsigned = 0;
-
-      // Index 4 is the total number of packets (based on block size).
-      set->abstruses.array[4].key = f_fss_payload_object_total_s;
-      set->abstruses.array[4].value.type = f_abstruse_unsigned_e;
-      set->abstruses.array[4].value.is.a_unsigned = 0;
-
-      // Index 5 is the name.
-      set->abstruses.array[5].key = f_fss_payload_object_name_s;
-      set->abstruses.array[5].value.type = f_abstruse_dynamic_e;
-      set->abstruses.array[5].value.is.a_dynamic = set->name;
-      set->abstruses.array[5].value.is.a_dynamic.size = 0;
-
-      // Index 6 is the salt.
-      set->abstruses.array[6].key = kt_tacocat_salt_s;
-      set->abstruses.array[6].value.type = f_abstruse_unsigned_e;
-
-      // Index 7 is the transaction id.
-      set->abstruses.array[7].key = f_fss_payload_object_id_s;
-      set->abstruses.array[7].value.type = f_abstruse_dynamic_e;
-      set->abstruses.array[7].value.is.a_dynamic = set->id;
-      set->abstruses.array[7].value.is.a_dynamic.size = 0;
+    set->status = f_memory_array_increase_by(kt_tacocat_packet_headers_d, sizeof(f_abstruse_map_t), (void **) &set->abstruses.array, &set->abstruses.used, &set->abstruses.size);
+    if (F_status_is_error(set->status)) return;
+
+    // Index 0 is the status.
+    set->abstruses.array[0].key = f_fss_payload_object_status_s;
+    set->abstruses.array[0].value.type = f_abstruse_dynamic_e;
+    set->abstruses.array[0].value.is.a_dynamic = f_status_okay_s;
+
+    // Index 1 is the type.
+    set->abstruses.array[1].key = f_fss_payload_object_type_s;
+    set->abstruses.array[1].value.type = f_abstruse_dynamic_e;
+    set->abstruses.array[1].value.is.a_dynamic = f_file_type_name_file_s;
+
+    // Index 2 is the length.
+    set->abstruses.array[2].key = f_fss_payload_object_length_s;
+    set->abstruses.array[2].value.type = f_abstruse_unsigned_e;
+    set->abstruses.array[2].value.is.a_unsigned = 0;
+
+    // Index 3 is the part.
+    set->abstruses.array[3].key = f_fss_payload_object_part_s;
+    set->abstruses.array[3].value.type = f_abstruse_unsigned_e;
+    set->abstruses.array[3].value.is.a_unsigned = 0;
+
+    // Index 4 is the total number of packets (based on block size).
+    set->abstruses.array[4].key = f_fss_payload_object_total_s;
+    set->abstruses.array[4].value.type = f_abstruse_unsigned_e;
+    set->abstruses.array[4].value.is.a_unsigned = 0;
+
+    // Index 5 is the name.
+    set->abstruses.array[5].key = f_fss_payload_object_name_s;
+    set->abstruses.array[5].value.type = f_abstruse_dynamic_e;
+    set->abstruses.array[5].value.is.a_dynamic = set->name;
+    set->abstruses.array[5].value.is.a_dynamic.size = 0;
+
+    // Index 6 is the salt.
+    set->abstruses.array[6].key = f_fss_payload_object_salt_s;
+    set->abstruses.array[6].value.type = f_abstruse_unsigned_e;
+
+    // Index 7 is the transaction id.
+    set->abstruses.array[7].key = f_fss_payload_object_id_s;
+    set->abstruses.array[7].value.type = f_abstruse_dynamic_e;
+    set->abstruses.array[7].value.is.a_dynamic = set->id;
+    set->abstruses.array[7].value.is.a_dynamic.size = 0;
+
+    // Index 8 is the time.
+    set->abstruses.array[8].key = f_fss_payload_object_time_s;
+    set->abstruses.array[8].value.type = f_abstruse_dynamic_e;
+    set->abstruses.array[8].value.is.a_dynamic = set->time;
+    set->abstruses.array[8].value.is.a_dynamic.size = 0;
 
-      {
-        long salt = 0;
+    {
+      long salt = 0;
 
-        f_random_get(&salt);
+      f_random_get(&salt);
 
-        set->abstruses.array[6].value.is.a_unsigned = (f_number_unsigned_t) salt;
-      }
+      set->abstruses.array[6].value.is.a_unsigned = (f_number_unsigned_t) salt;
+    }
 
-      set->abstruses.used = kt_tacocat_packet_headers_d;
+    set->abstruses.used = kt_tacocat_packet_headers_d;
   }
 #endif // _di_kt_tacocat_process_abstruse_initialize_
 
index 9f98e2fa4197a55d3d658d5c9e035c3eba09c356..b41711dcd8303a4d3674d2c0df3debb683ed6d21 100644 (file)
@@ -214,7 +214,7 @@ extern "C" {
     }
 
     if (set->step == kt_tacocat_socket_step_send_header_e) {
-      // @todo this needs to check the current status, accodingly (for when multiple blocks are being sent).
+      // @todo this needs to check the current status, accordingly (for when multiple blocks are being sent).
 
       // Reserve the FSS Packet header, which will be calculated just before sending.
       set->buffer.used = 5;
@@ -410,6 +410,7 @@ extern "C" {
     set->range.stop = 0;
     set->state.status = F_none;
     set->status = F_none;
+    set->time.used = 0;
     set->packet.control = 0;
     set->packet.size = 0;
     set->packet.payload.start = 1;
@@ -479,10 +480,62 @@ extern "C" {
     }
 
     if (F_status_is_error_not(set->status)) {
+      kt_tacocat_send_process_time_now(set);
+    }
+
+    if (F_status_is_error_not(set->status)) {
       kt_tacocat_process_abstruse_initialize(main, set);
     }
+
+    if (F_status_is_error_not(set->status)) {
+      set->status = F_okay;
+    }
   }
 #endif // _di_kt_tacocat_send_process_initialize_
+
+#ifndef _di_kt_tacocat_send_process_time_now_
+  void kt_tacocat_send_process_time_now(kt_tacocat_socket_set_t * const set) {
+
+    if (!set) return;
+
+    set->time.used = 0;
+
+    f_string_t string = f_string_t_initialize;
+
+    {
+      time_t t = time(NULL);
+
+      string = asctime(gmtime(&t));
+    }
+
+    if (string) {
+      f_number_unsigned_t total = strnlen(string, kt_tacocat_max_asctime_d);
+
+      // Do not count the NULL (some strnlen() implementations, like glibc, appear to incorrectly include the terminating NULL in the count.
+      if (total && !string[total]) {
+        --total;
+      }
+
+      set->status = f_memory_array_increase_by(total + kt_tacocat_time_utc_s.used + 1, sizeof(f_char_t), (void **) &set->time.string, &set->time.used, &set->time.size);
+      if (F_status_is_error(set->status)) return;
+
+      set->status = f_string_append(string, total, &set->time);
+      if (F_status_is_error(set->status)) return;
+
+      set->status = f_string_dynamic_append(kt_tacocat_time_utc_s, &set->time);
+      if (F_status_is_error(set->status)) return;
+
+      set->status = f_string_dynamic_terminate_after(&set->time);
+      if (F_status_is_error(set->status)) return;
+
+      set->status = F_okay;
+    }
+    else {
+      set->status = F_status_set_error(F_time);
+    }
+  }
+#endif // _di_kt_tacocat_send_process_time_now_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 556dea01a91e05535a750f358a16d9fdcddf686d..3c07b5515647152c7c4f767b6fd4ec950accdce1 100644 (file)
@@ -90,14 +90,48 @@ extern "C" {
  *
  *     Errors (with error bit) from: f_memory_array_increase_by()
  *     Errors (with error bit) from: kt_tacocat_process_abstruse_initialize()
+ *     Errors (with error bit) from: kt_tacocat_send_process_time_now()
  *
  * @see f_memory_array_increase_by()
  * @see kt_tacocat_process_abstruse_initialize()
+ * @see kt_tacocat_send_process_time_now()
  */
 #ifndef _di_kt_tacocat_send_process_initialize_
   extern void kt_tacocat_send_process_initialize(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
 #endif // _di_kt_tacocat_send_process_initialize_
 
+/**
+ * Build a string containing the current time.
+ *
+ * @param set
+ *   The socket set to process.
+ *   Must not be NULL.
+ *
+ *   The set.time is updated with the generated time string.
+ *
+ *   This alters set.status:
+ *     F_okay on success.
+ *
+ *     F_time (with error bit) on failure to get the time.
+ *
+ *     Errors (with error bit) from: f_memory_array_increase_by().
+ *     Errors (with error bit) from: f_string_append().
+ *     Errors (with error bit) from: f_string_dynamic_append().
+ *     Errors (with error bit) from: f_string_dynamic_terminate_after().
+ *
+ * @see f_memory_array_increase_by()
+ * @see f_string_append()
+ * @see f_string_dynamic_append()
+ * @see f_string_dynamic_terminate_after()
+ *
+ * @see asctime()
+ * @see gmtime()
+ * @see strnlen()
+ */
+#ifndef _di_kt_tacocat_send_process_time_now_
+  extern void kt_tacocat_send_process_time_now(kt_tacocat_socket_set_t * const set);
+#endif // _di_kt_tacocat_send_process_time_now_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif