]> Kevux Git Server - kevux-tools/commitdiff
Update: Break apart TacocaT send steps into multiple functions.
authorKevin Day <Kevin@kevux.org>
Mon, 24 Nov 2025 04:35:42 +0000 (22:35 -0600)
committerKevin Day <Kevin@kevux.org>
Mon, 24 Nov 2025 04:35:42 +0000 (22:35 -0600)
This adds a lot more files but cleans up the code quite a bit.
The `kt_tacocat_send_process()` function is now easier to read and follow.

I anticipate doing similar things to other parts of TacocaT.

25 files changed:
data/build/stand_alone/settings/settings.tacocat
data/build/tacocat/settings
sources/c/program/kevux/tools/tacocat/main/common/define.h
sources/c/program/kevux/tools/tacocat/main/common/string.c
sources/c/program/kevux/tools/tacocat/main/common/string.h
sources/c/program/kevux/tools/tacocat/main/send.c
sources/c/program/kevux/tools/tacocat/main/send/step/build.c [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/build.h [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/check.c [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/check.h [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/done.c [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/done.h [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/encode.c [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/encode.h [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/file.c [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/file.h [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/header.c [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/header.h [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/packet.c [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/packet.h [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/size.c [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/size.h [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/wait.c [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/send/step/wait.h [new file with mode: 0644]
sources/c/program/kevux/tools/tacocat/main/tacocat.h

index 716a9444f884ac03a9aa59a8cf5d9eba40a1881f..5fb2a481db08bfb452c6f46c9b27425a745a70db 100644 (file)
@@ -88,8 +88,10 @@ build_sources_program fll/level_2/fss.c fll/level_2/fss/basic.c fll/level_2/fss/
 build_sources_program fll/level_2/print.c
 build_sources_program fll/level_2/program.c fll/level_2/program/common.c fll/level_2/program/print.c fll/level_2/program/string.c fll/level_2/private-program.c
 
-build_sources_program program/kevux/tools/tacocat/main/common.c program/kevux/tools/tacocat/main/common/define.c program/kevux/tools/tacocat/main/common/enumeration.c program/kevux/tools/tacocat/main/common/string.c program/kevux/tools/tacocat/main/common/type.c program/kevux/tools/tacocat/main/print/error.c program/kevux/tools/tacocat/main/print/message.c program/kevux/tools/tacocat/main/print/verbose.c program/kevux/tools/tacocat/main/print/warning.c program/kevux/tools/tacocat/main/packet.c program/kevux/tools/tacocat/main/process.c program/kevux/tools/tacocat/main/receive.c program/kevux/tools/tacocat/main/send.c program/kevux/tools/tacocat/main/signal.c program/kevux/tools/tacocat/main/tacocat.c program/kevux/tools/tacocat/main/thread.c
-
+build_sources_program program/kevux/tools/tacocat/main/common.c program/kevux/tools/tacocat/main/common/define.c program/kevux/tools/tacocat/main/common/enumeration.c program/kevux/tools/tacocat/main/common/string.c program/kevux/tools/tacocat/main/common/type.c
+build_sources_program program/kevux/tools/tacocat/main/print/error.c program/kevux/tools/tacocat/main/print/message.c program/kevux/tools/tacocat/main/print/verbose.c program/kevux/tools/tacocat/main/print/warning.c
+build_sources_program program/kevux/tools/tacocat/main/packet.c program/kevux/tools/tacocat/main/process.c program/kevux/tools/tacocat/main/receive.c program/kevux/tools/tacocat/main/send.c program/kevux/tools/tacocat/main/signal.c program/kevux/tools/tacocat/main/tacocat.c program/kevux/tools/tacocat/main/thread.c
+build_sources_program program/kevux/tools/tacocat/main/send/step/build.c program/kevux/tools/tacocat/main/send/step/check.c program/kevux/tools/tacocat/main/send/step/done.c program/kevux/tools/tacocat/main/send/step/encode.c program/kevux/tools/tacocat/main/send/step/file.c program/kevux/tools/tacocat/main/send/step/header.c program/kevux/tools/tacocat/main/send/step/packet.c program/kevux/tools/tacocat/main/send/step/size.c program/kevux/tools/tacocat/main/send/step/wait.c
 build_sources_program program/kevux/tools/tacocat/tacocat/config.c program/kevux/tools/tacocat/tacocat/tacocat.c program/kevux/tools/tacocat/tacocat/main.c program/kevux/tools/tacocat/tacocat/string.c
 
 build_sources_documentation man
index 036870c9093034ddadc659c90ab5669bdad4f43b..73e61aaec376e8e3b841600a249f3e89fe557194 100644 (file)
@@ -53,9 +53,15 @@ build_libraries_static-individual_thread -l:libf_thread.a
 build_libraries_static-level -l:libfll_2.a -l:libfll_1.a -l:libfll_0.a
 build_libraries_static-monolithic -l:libfll.a
 
-build_sources_library common.c common/define.c common/enumeration.c common/string.c common/type.c print/error.c print/message.c print/verbose.c print/warning.c packet.c process.c receive.c send.c signal.c tacocat.c thread.c
-
-build_sources_headers common.h common/define.h common/enumeration.h common/string.h common/type.h print/error.h print/message.h print/verbose.h print/warning.h packet.h process.h receive.h send.h signal.h tacocat.h thread.h
+build_sources_library common.c common/define.c common/enumeration.c common/string.c common/type.c
+build_sources_library print/error.c print/message.c print/verbose.c print/warning.c
+build_sources_library packet.c process.c receive.c send.c signal.c tacocat.c thread.c
+build_sources_library send/step/build.c send/step/check.c send/step/done.c send/step/encode.c send/step/file.c send/step/header.c send/step/packet.c send/step/size.c send/step/wait.c
+
+build_sources_headers common.h common/define.h common/enumeration.h common/string.h common/type.h
+build_sources_headers print/error.h print/message.h print/verbose.h print/warning.h
+build_sources_headers packet.h process.h receive.h send.h signal.h tacocat.h thread.h
+build_sources_headers send/step/build.h send/step/check.h send/step/done.h send/step/encode.h send/step/file.h send/step/header.h send/step/packet.h send/step/size.h send/step/wait.h
 
 build_sources_documentation man
 
index a7f8260992324748efe9dd81a8a5b98e6965b013..0e8c65ea22f291bf47ebd02d3494403cf368e335 100644 (file)
@@ -110,9 +110,6 @@ extern "C" {
  *
  * These macros are intended to simplify repetitive parts of the code to improve readability.
  *
- * macro_kt_tacocat_handle_send_process_error_exit_1:
- *   Similar to macro_kt_tacocat_handle_receive_process_error_exit_1() but calls kt_tacocat_print_error_on_packet_invalid().
- *
  * macro_kt_tacocat_handle_load_send_receive_error_continue_1:
  *   For use in kt_tacocat_setting_load_send_receive().
  *   This is for the basic error that calls kt_tacocat_print_error() when printing.
@@ -203,13 +200,6 @@ extern "C" {
       \
       return; \
     }
-
-  #define macro_kt_tacocat_handle_send_process_error_exit_1(main, on, network, status, name, step) \
-    if (F_status_is_error(status)) { \
-      kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, on, network, status, name); \
-      \
-      return F_done_not; \
-    }
 #endif // _di_kt_tacocat_macro_d_
 
 /**
index bf5fbeff68d873d5a1f6739eca782fada07f4e30..868d0aaf7fe775488cbd2425596bc5f9177319f8 100644 (file)
@@ -29,9 +29,10 @@ extern "C" {
   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);
   const f_string_static_t kt_tacocat_send_connect_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_send_connect_s, 0, KT_TACOCAT_send_connect_s_length);
   const f_string_static_t kt_tacocat_send_done_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_send_done_s, 0, KT_TACOCAT_send_done_s_length);
+  const f_string_static_t kt_tacocat_send_encode_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_send_encode_s, 0, KT_TACOCAT_send_encode_s_length);
   const f_string_static_t kt_tacocat_send_file_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_send_file_s, 0, KT_TACOCAT_send_file_s_length);
   const f_string_static_t kt_tacocat_send_header_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_send_header_s, 0, KT_TACOCAT_send_header_s_length);
-  const f_string_static_t kt_tacocat_send_payload_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_send_payload_s, 0, KT_TACOCAT_send_payload_s_length);
+  const f_string_static_t kt_tacocat_send_packet_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_send_packet_s, 0, KT_TACOCAT_send_packet_s_length);
   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);
index 94da0f7baa0bdefe36079027a9bbdf8bb5f8f667..69cf24c437906cb0d4d6273690ad7edf2a1dee13 100644 (file)
@@ -82,9 +82,10 @@ extern "C" {
   #define KT_TACOCAT_send_combine_s       "send combine"
   #define KT_TACOCAT_send_connect_s       "send connect"
   #define KT_TACOCAT_send_done_s          "send done"
+  #define KT_TACOCAT_send_encode_s        "send encode"
   #define KT_TACOCAT_send_file_s          "send file"
   #define KT_TACOCAT_send_header_s        "send header"
-  #define KT_TACOCAT_send_payload_s       "send payload"
+  #define KT_TACOCAT_send_packet_s        "send packet"
   #define KT_TACOCAT_send_size_s          "send size"
   #define KT_TACOCAT_socket_s             "socket"
   #define KT_TACOCAT_tacocat_s            "tacocat"
@@ -107,9 +108,10 @@ extern "C" {
   #define KT_TACOCAT_send_combine_s_length       12
   #define KT_TACOCAT_send_connect_s_length       12
   #define KT_TACOCAT_send_done_s_length          9
+  #define KT_TACOCAT_send_encode_s_length        11
   #define KT_TACOCAT_send_file_s_length          9
   #define KT_TACOCAT_send_header_s_length        11
-  #define KT_TACOCAT_send_payload_s_length       12
+  #define KT_TACOCAT_send_packet_s_length        11
   #define KT_TACOCAT_send_size_s_length          9
   #define KT_TACOCAT_socket_s_length             6
   #define KT_TACOCAT_tacocat_s_length            7
@@ -132,9 +134,10 @@ extern "C" {
   extern const f_string_static_t kt_tacocat_send_combine_s;
   extern const f_string_static_t kt_tacocat_send_connect_s;
   extern const f_string_static_t kt_tacocat_send_done_s;
+  extern const f_string_static_t kt_tacocat_send_encode_s;
   extern const f_string_static_t kt_tacocat_send_file_s;
   extern const f_string_static_t kt_tacocat_send_header_s;
-  extern const f_string_static_t kt_tacocat_send_payload_s;
+  extern const f_string_static_t kt_tacocat_send_packet_s;
   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;
index 7ef19f69a1eb43e746acbcd8ca3f5c947b08b46f..420003126d2c14f292d01331cf87e5d812954602 100644 (file)
@@ -97,7 +97,9 @@ extern "C" {
       kt_tacocat_send_process_initialize(main, set);
 
       if (F_status_is_error(set->status)) {
-        macro_kt_tacocat_handle_send_process_error_exit_1(main, kt_tacocat_send_s, set->network, set->status, set->name, set->step);
+        kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, kt_tacocat_send_s, set->network, set->status, set->name);
+
+        return F_done_not;
       }
 
       set->step = kt_tacocat_socket_step_send_size_e;
@@ -120,262 +122,42 @@ extern "C" {
 
     // @todo when total > 1, then this needs to build each part, incrementing part each time (every time this needs to be done, the entire header structure needs to be rebuilt until part == total - 1) (the receive code needs to also be sure to handle multiple parts).
     if (set->step == kt_tacocat_socket_step_send_size_e) {
-      if (set->file.id == -1) {
-        set->status = f_file_open(set->name, F_file_mode_all_r_d, &set->file);
-
-        if (F_status_is_error(set->status)) {
-          kt_tacocat_print_error_on_file_receive(&main->program.error, F_status_debug_source_d, kt_tacocat_send_s, set->network, set->status, set->name, f_file_operation_open_s);
-
-          return F_done_not;
-        }
-      }
-
-      // Total is used here to explicitly pass a pointer of off_t rather than a pointer of size_t cast to an off_t.
-      off_t total = 0;
-
-      set->status = f_file_size_by_id(set->file, &total);
-
-      if (F_status_is_error(set->status)) {
-        kt_tacocat_print_error_on_file_receive(&main->program.error, F_status_debug_source_d, kt_tacocat_send_size_s, set->network, set->status, set->name, f_file_operation_open_s);
-
-        return F_done_not;
-      }
-
-      if ((f_number_unsigned_t) total > F_number_t_size_unsigned_d) {
-        set->status = F_status_set_error(F_too_large);
-
-        kt_tacocat_print_error_on_file_too_large(&main->program.error, set->name, kt_tacocat_send_size_s, set->network, F_number_t_size_unsigned_d, set->abstruses.array[4].value.is.a_unsigned);
-
-        return F_done_not;
-      }
-
-      set->abstruses.array[3].value.is.a_unsigned = 0;
-      set->size_total = (f_number_unsigned_t) total;
-
-      if (total) {
-        if (set->size_total < set->file.size_read) {
-          set->abstruses.array[2].value.is.a_unsigned = set->size_total;
-          set->abstruses.array[4].value.is.a_unsigned = 1;
-        }
-        else {
-          set->abstruses.array[2].value.is.a_unsigned = set->file.size_read;
-          set->abstruses.array[4].value.is.a_unsigned = set->size_total / set->file.size_read;
-
-          if (set->abstruses.array[4].value.is.a_unsigned % set->file.size_read) {
-            ++set->abstruses.array[4].value.is.a_unsigned;
-          }
-        }
-      }
-      else {
-        set->abstruses.array[2].value.is.a_unsigned = set->size_total;
-        set->abstruses.array[4].value.is.a_unsigned = 1;
-      }
-
-      set->status = f_memory_array_increase_by(set->abstruses.array[4].value.is.a_unsigned, sizeof(f_number_unsigned_t), (void **) &set->parts.array, &set->parts.used, &set->parts.size);
-
-      if (F_status_is_error(set->status)) {
-        // @todo out of memory, send abort packet with F_memory as a status.
-        // @todo pre-build an out of memory packet as a static string, with reserved space for the salt.
-        // @todo packets like this need to be sent
-        f_file_close(&set->file);
-        f_socket_disconnect(&set->socket, f_socket_close_fast_e);
-
-        set->step = 0;
-        set->socket.id_data = -1;
-
-        // Keep error bit but set state to done to designate that nothing else is to be done.
-        set->status = F_status_set_error(F_done);
-
-        kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, kt_tacocat_send_size_s, set->network, set->status, set->name);
-
-        return F_done_not;
-      }
-
-      set->step = kt_tacocat_socket_step_send_build_e;
+      kt_tacocat_send_step_size(main, set);
     }
 
     if (set->step == kt_tacocat_socket_step_send_build_e) {
-      f_state_t state_local = main->setting.state;
-      state_local.data = &set->write_state;
-
-      fl_fss_payload_header_map(set->abstruses, &set->headers, &state_local);
-
-      set->status = state_local.status;
-
-      macro_kt_tacocat_handle_send_process_error_exit_1(main, kt_tacocat_send_build_s, set->network, set->status, set->name, set->step);
-
-      set->write_state.cache->used = 0;
-
-      set->status = f_random_array_shuffle(0, set->headers.used, sizeof(f_string_map_t), set->write_state.cache, (void *) set->headers.array);
-
-      macro_kt_tacocat_handle_send_process_error_exit_1(main, kt_tacocat_send_build_s, set->network, set->status, set->name, set->step);
-
-      set->step = kt_tacocat_socket_step_send_header_e;
+      kt_tacocat_send_step_build(main, set);
     }
 
     if (set->step == kt_tacocat_socket_step_send_header_e) {
-      // @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;
-      memset(set->buffer.string, 0, 5);
-
-      set->status = f_string_dynamic_append_nulless(f_fss_payload_comment_header_begin_s, &set->buffer);
-
-      if (F_status_is_error_not(set->status)) {
-        set->status = f_string_dynamic_append_nulless(f_fss_payload_comment_header_s, &set->buffer);
-      }
-
-      if (F_status_is_error_not(set->status)) {
-        set->status = f_string_dynamic_append_nulless(f_fss_payload_comment_header_end_s, &set->buffer);
-      }
-
-      if (F_status_is_error_not(set->status)) {
-        set->status = f_string_dynamic_append_nulless(f_fss_payload_object_header_s, &set->buffer);
-      }
-
-      if (F_status_is_error_not(set->status)) {
-        set->status = f_string_dynamic_append_nulless(f_fss_payload_object_end_s, &set->buffer);
-      }
-
-      if (F_status_is_error_not(set->status)) {
-        for (f_number_unsigned_t i = 0; i < set->headers.used; ++i) {
-
-          set->status = f_string_dynamic_append_nulless(set->headers.array[i].key, &set->buffer);
-
-          if (F_status_is_error_not(set->status)) {
-            set->status = f_string_dynamic_append_nulless(f_fss_extended_open_s, &set->buffer);
-          }
-
-          if (F_status_is_error_not(set->status)) {
-            set->status = f_string_dynamic_append_nulless(set->headers.array[i].value, &set->buffer);
-          }
-
-          if (F_status_is_error_not(set->status)) {
-            set->status = f_string_dynamic_append_nulless(f_fss_extended_close_s, &set->buffer);
-          }
-          else {
-            break;
-          }
-        } // for
-      }
-
-      macro_kt_tacocat_handle_send_process_error_exit_1(main, kt_tacocat_send_combine_s, set->network, set->status, set->name, set->step);
-
-      set->step = kt_tacocat_socket_step_send_file_e;
+      kt_tacocat_send_step_header(main, set);
     }
 
     if (set->step == kt_tacocat_socket_step_send_file_e) {
-      const f_number_unsigned_t size_header = set->buffer.used;
-
-      set->status = f_string_dynamic_append(f_fss_payload_object_payload_s, &set->buffer);
-
-      if (F_status_is_error_not(set->status)) {
-        set->status = f_string_dynamic_append(f_fss_payload_object_end_s, &set->buffer);
-      }
-
-      macro_kt_tacocat_handle_send_process_error_exit_1(main, kt_tacocat_send_file_s, set->network, set->status, set->name, set->step);
-
-      // Always reset the seek position in case a retry happened after the file block is read.
-      {
-        off_t seeked = 0;
-
-        set->status = f_file_seek(set->file, SEEK_SET, set->size_done, &seeked);
-        macro_kt_tacocat_handle_send_process_error_exit_1(main, kt_tacocat_send_file_s, set->network, set->status, set->name, set->step);
-      }
-
-      set->status = f_file_read_block(set->file, &set->buffer);
-      macro_kt_tacocat_handle_send_process_error_exit_1(main, kt_tacocat_send_file_s, set->network, set->status, set->name, set->step);
-
-      set->status = f_string_dynamic_terminate_after(&set->buffer);
-      macro_kt_tacocat_handle_send_process_error_exit_1(main, kt_tacocat_send_combine_s, set->network, set->status, set->name, set->step);
-
-      set->retry = 0;
-      set->step = kt_tacocat_socket_step_send_check_e;
+      kt_tacocat_send_step_file(main, set);
     }
 
     if (set->step == kt_tacocat_socket_step_send_check_e) {
-      // @todo this needs to check if the size read has changed and then re-build the header (swap the buffer read block into the cache then rebuild the header with th new size).
-      //if (set->abstruses.array[2].value.is.a_unsigned < set->file.size_read) {
-      //}
-
-      set->step = kt_tacocat_socket_step_send_encode_e;
+      kt_tacocat_send_step_check(main, set);
     }
 
     if (set->step == kt_tacocat_socket_step_send_encode_e) {
-      const f_number_unsigned_t original = set->buffer.used;
-
-      set->buffer.used = 0;
-
-      // @todo there will need to be checks for max-size and the payload size, shrinking the payload if the header + payload is too large.
-      // @todo if the header file is so large that the payload is smaller than a reasonable minumum (say 32 bytes), then this is a problem and throw a too large/small error.
-      set->status = f_fss_simple_packet_encode(F_fss_simple_packet_endian_d, original, &set->buffer);
-
-      set->buffer.used = original;
-
-      macro_kt_tacocat_handle_send_process_error_exit_1(main, kt_tacocat_send_payload_s, set->network, set->status, set->name, set->step);
-
-      set->step = kt_tacocat_socket_step_send_packet_e;
+      kt_tacocat_send_step_encode(main, set);
     }
 
     if (set->step == kt_tacocat_socket_step_send_packet_e) {
-      size_t written = 0;
-
-      {
-        const size_t original = set->socket.size_write;
-
-        set->socket.size_write = set->buffer.used;
-
-        set->status = f_socket_write_stream(&set->socket, f_socket_flag_signal_not_e, (void *) set->buffer.string, &written);
-
-        set->socket.size_write = original;
-
-        macro_kt_tacocat_handle_send_process_error_exit_1(main, kt_tacocat_send_payload_s, set->network, set->status, set->name, set->step);
-      }
-
-      // @todo handle case when written < set->buffer.used, of which each pass. The entire buffer must be sent. May need another variable for say, set->size_process.
-
-      set->size_done += written;
-
-      set->status = F_okay;
-      set->step = kt_tacocat_socket_step_send_wait_e;
+      kt_tacocat_send_step_packet(main, set);
 
       // Wait for packet received confirmation.
       return F_done_not;
     }
 
     if (set->step == kt_tacocat_socket_step_send_wait_e) {
-      // @todo process/validate the received response.
-
-      // When the buffer is smaller than the read block size, then the entire file should be completely sent.
-      if (set->size_done >= set->buffer.used) {
-        set->step = kt_tacocat_socket_step_send_done_e;
-      }
-      else {
-        set->status = F_okay;
-        set->step = kt_tacocat_socket_step_send_wait_e;
-
-        return F_done_not;
-      }
+      if (kt_tacocat_send_step_wait(main, set) == F_complete_not) return F_done_not;
     }
 
     if (set->step == kt_tacocat_socket_step_send_done_e) {
-      //@todo send done packet.
-      set->status = f_file_close(&set->file);
-
-      if (F_status_is_error(set->status)) {
-        kt_tacocat_print_warning_on_file(&main->program.warning, F_status_debug_source_d, kt_tacocat_send_done_s, set->network, set->status, set->name, f_file_operation_close_s);
-      }
-
-      set->status = f_socket_disconnect(&set->socket, f_socket_close_fast_e);
-
-      if (F_status_is_error(set->status)) {
-        kt_tacocat_print_warning_on_file(&main->program.warning, F_status_debug_source_d, kt_tacocat_send_done_s, set->network, set->status, set->name, f_file_operation_close_s);
-      }
-
-      set->step = 0;
-      set->socket.id_data = -1;
-      set->status = F_okay;
+      kt_tacocat_send_step_done(main, set);
 
       return F_done;
     }
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/build.c b/sources/c/program/kevux/tools/tacocat/main/send/step/build.c
new file mode 100644 (file)
index 0000000..8f07bc5
--- /dev/null
@@ -0,0 +1,44 @@
+#include "../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_tacocat_send_step_build_
+  void kt_tacocat_send_step_build(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+    if (!main || !set || F_status_is_error(set->status)) return;
+
+    {
+      f_state_t state = main->setting.state;
+      state.data = &set->write_state;
+
+      fl_fss_payload_header_map(set->abstruses, &set->headers, &state);
+
+      if (F_status_is_error(state.status)) {
+        set->status = state.status;
+
+        kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, kt_tacocat_send_build_s, set->network, set->status, set->name);
+
+        return;
+      }
+    }
+
+    set->write_state.cache->used = 0;
+
+    set->status = f_random_array_shuffle(0, set->headers.used, sizeof(f_string_map_t), set->write_state.cache, (void *) set->headers.array);
+
+    if (F_status_is_error(set->status)) {
+      kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, kt_tacocat_send_build_s, set->network, set->status, set->name);
+
+      return;
+    }
+
+    set->step = kt_tacocat_socket_step_send_header_e;
+    set->status = F_okay;
+  }
+#endif // _di_kt_tacocat_send_step_build_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/build.h b/sources/c/program/kevux/tools/tacocat/main/send/step/build.h
new file mode 100644 (file)
index 0000000..24b653a
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides send step build functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_send_step_build_h
+#define _kt_tacocat_send_step_build_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the build step of a send request.
+ *
+ * This prints on error.
+ *
+ * @param main
+ *   The main program and settings data.
+ *
+ *   Must not be NULL.
+ *
+ *   This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ *   The socket set to process.
+ *
+ *   Must not be NULL.
+ *
+ *   This alters set.status:
+ *     F_okay on success.
+ *
+ *     Errors (with error bit) from: f_random_array_shuffle()
+ *     Errors (with error bit) from: fl_fss_payload_header_map()
+ *
+ * @see f_random_array_shuffle()
+ * @see fl_fss_payload_header_map()
+ */
+#ifndef _di_kt_tacocat_send_step_build_
+  extern void kt_tacocat_send_step_build(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // _di_kt_tacocat_send_step_build_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_send_step_build_h
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/check.c b/sources/c/program/kevux/tools/tacocat/main/send/step/check.c
new file mode 100644 (file)
index 0000000..456549e
--- /dev/null
@@ -0,0 +1,22 @@
+#include "../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_tacocat_send_step_check_
+  void kt_tacocat_send_step_check(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+    if (!main || !set || F_status_is_error(set->status)) return;
+
+    // @todo this needs to check if the size read has changed and then re-build the header (swap the buffer read block into the cache then rebuild the header with th new size).
+    //if (set->abstruses.array[2].value.is.a_unsigned < set->file.size_read) {
+    //}
+
+    set->step = kt_tacocat_socket_step_send_encode_e;
+  }
+#endif // _di_kt_tacocat_send_step_check_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/check.h b/sources/c/program/kevux/tools/tacocat/main/send/step/check.h
new file mode 100644 (file)
index 0000000..34936f9
--- /dev/null
@@ -0,0 +1,46 @@
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides send step check functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_send_step_check_h
+#define _kt_tacocat_send_step_check_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the check step of a send request.
+ *
+ * This prints on error.
+ *
+ * @param main
+ *   The main program and settings data.
+ *
+ *   Must not be NULL.
+ *
+ *   This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ *   The socket set to process.
+ *
+ *   Must not be NULL.
+ *
+ *   This alters set.status:
+ *     F_okay on success.
+ */
+#ifndef _di_kt_tacocat_send_step_check_
+  extern void kt_tacocat_send_step_check(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // _di_kt_tacocat_send_step_check_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_send_step_check_h
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/done.c b/sources/c/program/kevux/tools/tacocat/main/send/step/done.c
new file mode 100644 (file)
index 0000000..b324444
--- /dev/null
@@ -0,0 +1,34 @@
+#include "../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_tacocat_send_step_done_
+  void kt_tacocat_send_step_done(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+    if (!main || !set || F_status_is_error(set->status)) return;
+
+    //@todo send done packet.
+
+    set->status = f_file_close(&set->file);
+
+    if (F_status_is_error(set->status)) {
+      kt_tacocat_print_warning_on_file(&main->program.warning, F_status_debug_source_d, kt_tacocat_send_done_s, set->network, set->status, set->name, f_file_operation_close_s);
+    }
+
+    set->status = f_socket_disconnect(&set->socket, f_socket_close_fast_e);
+
+    if (F_status_is_error(set->status)) {
+      kt_tacocat_print_warning_on_file(&main->program.warning, F_status_debug_source_d, kt_tacocat_send_done_s, set->network, set->status, set->name, f_file_operation_close_s);
+    }
+
+    set->step = 0;
+    set->socket.id_data = -1;
+    set->status = F_okay;
+  }
+#endif // _di_kt_tacocat_send_step_done_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/done.h b/sources/c/program/kevux/tools/tacocat/main/send/step/done.h
new file mode 100644 (file)
index 0000000..daee00e
--- /dev/null
@@ -0,0 +1,46 @@
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides send step done functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_send_step_done_h
+#define _kt_tacocat_send_step_done_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the done step of a send request.
+ *
+ * This prints on error.
+ *
+ * @param main
+ *   The main program and settings data.
+ *
+ *   Must not be NULL.
+ *
+ *   This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ *   The socket set to process.
+ *
+ *   Must not be NULL.
+ *
+ *   This alters set.status:
+ *     F_okay on success.
+ */
+#ifndef _di_kt_tacocat_send_step_done_
+  extern void kt_tacocat_send_step_done(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // _di_kt_tacocat_send_step_done_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_send_step_done_h
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/encode.c b/sources/c/program/kevux/tools/tacocat/main/send/step/encode.c
new file mode 100644 (file)
index 0000000..90f197a
--- /dev/null
@@ -0,0 +1,37 @@
+#include "../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_tacocat_send_step_encode_
+  void kt_tacocat_send_step_encode(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+    if (!main || !set || F_status_is_error(set->status)) return;
+
+    {
+      const f_number_unsigned_t original = set->buffer.used;
+
+      set->buffer.used = 0;
+
+      // @todo there will need to be checks for max-size and the payload size, shrinking the payload if the header + payload is too large.
+      // @todo if the header file is so large that the payload is smaller than a reasonable minumum (say 32 bytes), then this is a problem and throw a too large/small error.
+      set->status = f_fss_simple_packet_encode(F_fss_simple_packet_endian_d, original, &set->buffer);
+
+      set->buffer.used = original;
+    }
+
+    if (F_status_is_error(set->status)) {
+      kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, kt_tacocat_send_encode_s, set->network, set->status, set->name);
+
+      return;
+    }
+
+    set->step = kt_tacocat_socket_step_send_packet_e;
+    set->status = F_okay;
+  }
+#endif // _di_kt_tacocat_send_step_encode_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/encode.h b/sources/c/program/kevux/tools/tacocat/main/send/step/encode.h
new file mode 100644 (file)
index 0000000..59a6ee1
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides send step encode functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_send_step_encode_h
+#define _kt_tacocat_send_step_encode_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the encode step of a send request.
+ *
+ * This prints on error.
+ *
+ * @param main
+ *   The main program and settings data.
+ *
+ *   Must not be NULL.
+ *
+ *   This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ *   The socket set to process.
+ *
+ *   Must not be NULL.
+ *
+ *   This alters set.status:
+ *     F_okay on success.
+ *
+ *     F_done (with error bit) on error that cannot continue, such as out of memory.
+ *     F_too_large (with error bit) on file too large.
+ *
+ *     Errors (with error bit) from: f_file_open()
+ *     Errors (with error bit) from: f_file_size_by_id()
+ *     Errors (with error bit) from: f_memory_array_increase_by()
+ *
+ * @see f_file_open()
+ * @see f_file_size_by_id()
+ * @see f_memory_array_increase_by()
+ */
+#ifndef _di_kt_tacocat_send_step_encode_
+  extern void kt_tacocat_send_step_encode(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // _di_kt_tacocat_send_step_encode_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_send_step_encode_h
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/file.c b/sources/c/program/kevux/tools/tacocat/main/send/step/file.c
new file mode 100644 (file)
index 0000000..ccf3497
--- /dev/null
@@ -0,0 +1,47 @@
+#include "../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_tacocat_send_step_file_
+  void kt_tacocat_send_step_file(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+    if (!main || !set || F_status_is_error(set->status)) return;
+
+    set->status = f_string_dynamic_append(f_fss_payload_object_payload_s, &set->buffer);
+
+    if (F_status_is_error_not(set->status)) {
+      set->status = f_string_dynamic_append(f_fss_payload_object_end_s, &set->buffer);
+    }
+
+    // Always reset the seek position in case a retry happened after the file block is read.
+    if (F_status_is_error_not(set->status)) {
+      off_t seeked = 0;
+
+      set->status = f_file_seek(set->file, SEEK_SET, set->size_done, &seeked);
+    }
+
+    if (F_status_is_error_not(set->status)) {
+      set->status = f_file_read_block(set->file, &set->buffer);
+    }
+
+    if (F_status_is_error_not(set->status)) {
+      set->status = f_string_dynamic_terminate_after(&set->buffer);
+    }
+
+    if (F_status_is_error(set->status)) {
+      kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, kt_tacocat_send_file_s, set->network, set->status, set->name);
+
+      return;
+    }
+
+    set->retry = 0;
+    set->step = kt_tacocat_socket_step_send_check_e;
+    set->status = F_okay;
+  }
+#endif // _di_kt_tacocat_send_step_file_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/file.h b/sources/c/program/kevux/tools/tacocat/main/send/step/file.h
new file mode 100644 (file)
index 0000000..2981eee
--- /dev/null
@@ -0,0 +1,56 @@
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides send step file functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_send_step_file_h
+#define _kt_tacocat_send_step_file_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the file step of a send request.
+ *
+ * This prints on error.
+ *
+ * @param main
+ *   The main program and settings data.
+ *
+ *   Must not be NULL.
+ *
+ *   This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ *   The socket set to process.
+ *
+ *   Must not be NULL.
+ *
+ *   This alters set.status:
+ *     F_okay on success.
+ *
+ *     Errors (with error bit) from: f_file_read_block()
+ *     Errors (with error bit) from: f_file_seek()
+ *     Errors (with error bit) from: f_string_dynamic_append()
+ *     Errors (with error bit) from: f_string_dynamic_terminate_after()
+ *
+ * @see f_file_read_block()
+ * @see f_file_seek()
+ * @see f_string_dynamic_append()
+ * @see f_string_dynamic_terminate_after()
+ */
+#ifndef _di_kt_tacocat_send_step_file_
+  extern void kt_tacocat_send_step_file(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // _di_kt_tacocat_send_step_file_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_send_step_file_h
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/header.c b/sources/c/program/kevux/tools/tacocat/main/send/step/header.c
new file mode 100644 (file)
index 0000000..a2f9b2c
--- /dev/null
@@ -0,0 +1,71 @@
+#include "../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_tacocat_send_step_header_
+  void kt_tacocat_send_step_header(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+    if (!main || !set || F_status_is_error(set->status)) return;
+
+    // @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;
+    memset(set->buffer.string, 0, 5);
+
+    set->status = f_string_dynamic_append_nulless(f_fss_payload_comment_header_begin_s, &set->buffer);
+
+    if (F_status_is_error_not(set->status)) {
+      set->status = f_string_dynamic_append_nulless(f_fss_payload_comment_header_s, &set->buffer);
+    }
+
+    if (F_status_is_error_not(set->status)) {
+      set->status = f_string_dynamic_append_nulless(f_fss_payload_comment_header_end_s, &set->buffer);
+    }
+
+    if (F_status_is_error_not(set->status)) {
+      set->status = f_string_dynamic_append_nulless(f_fss_payload_object_header_s, &set->buffer);
+    }
+
+    if (F_status_is_error_not(set->status)) {
+      set->status = f_string_dynamic_append_nulless(f_fss_payload_object_end_s, &set->buffer);
+    }
+
+    if (F_status_is_error_not(set->status)) {
+      for (f_number_unsigned_t i = 0; i < set->headers.used; ++i) {
+
+        set->status = f_string_dynamic_append_nulless(set->headers.array[i].key, &set->buffer);
+
+        if (F_status_is_error_not(set->status)) {
+          set->status = f_string_dynamic_append_nulless(f_fss_extended_open_s, &set->buffer);
+        }
+
+        if (F_status_is_error_not(set->status)) {
+          set->status = f_string_dynamic_append_nulless(set->headers.array[i].value, &set->buffer);
+        }
+
+        if (F_status_is_error_not(set->status)) {
+          set->status = f_string_dynamic_append_nulless(f_fss_extended_close_s, &set->buffer);
+        }
+        else {
+          break;
+        }
+      } // for
+    }
+
+    if (F_status_is_error(set->status)) {
+      kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, kt_tacocat_send_combine_s, set->network, set->status, set->name);
+
+      return;
+    }
+
+    set->step = kt_tacocat_socket_step_send_file_e;
+    set->status = F_okay;
+  }
+#endif // _di_kt_tacocat_send_step_header_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/header.h b/sources/c/program/kevux/tools/tacocat/main/send/step/header.h
new file mode 100644 (file)
index 0000000..b4d74c3
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides send step header functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_send_step_header_h
+#define _kt_tacocat_send_step_header_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the header step of a send request.
+ *
+ * This prints on error.
+ *
+ * @param main
+ *   The main program and settings data.
+ *
+ *   Must not be NULL.
+ *
+ *   This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ *   The socket set to process.
+ *
+ *   Must not be NULL.
+ *
+ *   This alters set.status:
+ *     F_okay on success.
+ *
+ *     Errors (with error bit) from: f_string_dynamic_append_nulless()
+ *
+ * @see f_string_dynamic_append_nulless()
+ */
+#ifndef _di_kt_tacocat_send_step_header_
+  extern void kt_tacocat_send_step_header(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // _di_kt_tacocat_send_step_header_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_send_step_header_h
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/packet.c b/sources/c/program/kevux/tools/tacocat/main/send/step/packet.c
new file mode 100644 (file)
index 0000000..1252eaa
--- /dev/null
@@ -0,0 +1,43 @@
+#include "../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_tacocat_send_step_packet_
+  void kt_tacocat_send_step_packet(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+    if (!main || !set || F_status_is_error(set->status)) return;
+
+    {
+      size_t written = 0;
+
+      {
+        const size_t original = set->socket.size_write;
+
+        set->socket.size_write = set->buffer.used;
+
+        set->status = f_socket_write_stream(&set->socket, f_socket_flag_signal_not_e, (void *) set->buffer.string, &written);
+
+        set->socket.size_write = original;
+
+        if (F_status_is_error(set->status)) {
+          kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, kt_tacocat_send_packet_s, set->network, set->status, set->name);
+
+          return;
+        }
+      }
+
+      // @todo handle case when written < set->buffer.used, of which each pass. The entire buffer must be sent. May need another variable for say, set->size_process.
+
+      set->size_done += written;
+    }
+
+    set->step = kt_tacocat_socket_step_send_wait_e;
+    set->status = F_okay;
+  }
+#endif // _di_kt_tacocat_send_step_packet_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/packet.h b/sources/c/program/kevux/tools/tacocat/main/send/step/packet.h
new file mode 100644 (file)
index 0000000..4573a1f
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides send step packet functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_send_step_packet_h
+#define _kt_tacocat_send_step_packet_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the packet step of a send request.
+ *
+ * This prints on error.
+ *
+ * @param main
+ *   The main program and settings data.
+ *
+ *   Must not be NULL.
+ *
+ *   This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ *   The socket set to process.
+ *
+ *   Must not be NULL.
+ *
+ *   This alters set.status:
+ *     F_okay on success.
+ *
+ *     Errors (with error bit) from: f_socket_write_stream()
+ *
+ * @see f_socket_write_stream()
+ */
+#ifndef _di_kt_tacocat_send_step_packet_
+  extern void kt_tacocat_send_step_packet(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // _di_kt_tacocat_send_step_packet_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_send_step_packet_h
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/size.c b/sources/c/program/kevux/tools/tacocat/main/send/step/size.c
new file mode 100644 (file)
index 0000000..3eb176f
--- /dev/null
@@ -0,0 +1,91 @@
+#include "../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_tacocat_send_step_size_
+  void kt_tacocat_send_step_size(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+    if (!main || !set || F_status_is_error(set->status)) return;
+
+    if (set->file.id == -1) {
+      set->status = f_file_open(set->name, F_file_mode_all_r_d, &set->file);
+
+      if (F_status_is_error(set->status)) {
+        kt_tacocat_print_error_on_file_receive(&main->program.error, F_status_debug_source_d, kt_tacocat_send_s, set->network, set->status, set->name, f_file_operation_open_s);
+
+        return;
+      }
+    }
+
+    // Total is used here to explicitly pass a pointer of off_t rather than a pointer of size_t cast to an off_t.
+    {
+      off_t total = 0;
+
+      set->status = f_file_size_by_id(set->file, &total);
+
+      if (F_status_is_error(set->status)) {
+        kt_tacocat_print_error_on_file_receive(&main->program.error, F_status_debug_source_d, kt_tacocat_send_size_s, set->network, set->status, set->name, f_file_operation_open_s);
+
+        return;
+      }
+
+      if ((f_number_unsigned_t) total > F_number_t_size_unsigned_d) {
+        set->status = F_status_set_error(F_too_large);
+
+        kt_tacocat_print_error_on_file_too_large(&main->program.error, set->name, kt_tacocat_send_size_s, set->network, F_number_t_size_unsigned_d, set->abstruses.array[4].value.is.a_unsigned);
+
+        return;
+      }
+
+      set->abstruses.array[3].value.is.a_unsigned = 0;
+      set->size_total = (f_number_unsigned_t) total;
+
+      if (total) {
+        if (set->size_total < set->file.size_read) {
+          set->abstruses.array[2].value.is.a_unsigned = set->size_total;
+          set->abstruses.array[4].value.is.a_unsigned = 1;
+        }
+        else {
+          set->abstruses.array[2].value.is.a_unsigned = set->file.size_read;
+          set->abstruses.array[4].value.is.a_unsigned = set->size_total / set->file.size_read;
+
+          if (set->abstruses.array[4].value.is.a_unsigned % set->file.size_read) {
+            ++set->abstruses.array[4].value.is.a_unsigned;
+          }
+        }
+      }
+      else {
+        set->abstruses.array[2].value.is.a_unsigned = set->size_total;
+        set->abstruses.array[4].value.is.a_unsigned = 1;
+      }
+    }
+
+    set->status = f_memory_array_increase_by(set->abstruses.array[4].value.is.a_unsigned, sizeof(f_number_unsigned_t), (void **) &set->parts.array, &set->parts.used, &set->parts.size);
+
+    if (F_status_is_error(set->status)) {
+      // @todo out of memory, send abort packet with F_memory as a status.
+      // @todo pre-build an out of memory packet as a static string, with reserved space for the salt.
+      // @todo packets like this need to be sent
+      f_file_close(&set->file);
+      f_socket_disconnect(&set->socket, f_socket_close_fast_e);
+
+      set->step = 0;
+      set->socket.id_data = -1;
+
+      // Keep error bit but set state to done to designate that nothing else is to be done.
+      set->status = F_status_set_error(F_done);
+
+      kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, kt_tacocat_send_size_s, set->network, set->status, set->name);
+
+      return;
+    }
+
+    set->step = kt_tacocat_socket_step_send_build_e;
+  }
+#endif // _di_kt_tacocat_send_step_size_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/size.h b/sources/c/program/kevux/tools/tacocat/main/send/step/size.h
new file mode 100644 (file)
index 0000000..7650cd0
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides send step size functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_send_step_size_h
+#define _kt_tacocat_send_step_size_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the size step of a send request.
+ *
+ * This prints on error.
+ *
+ * @param main
+ *   The main program and settings data.
+ *
+ *   Must not be NULL.
+ *
+ *   This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ *   The socket set to process.
+ *
+ *   Must not be NULL.
+ *
+ *   This alters set.status:
+ *     F_okay on success.
+ *
+ *     F_done (with error bit) on error that cannot continue, such as out of memory.
+ *     F_too_large (with error bit) on file too large.
+ *
+ *     Errors (with error bit) from: f_file_open()
+ *     Errors (with error bit) from: f_file_size_by_id()
+ *     Errors (with error bit) from: f_memory_array_increase_by()
+ *
+ * @see f_file_open()
+ * @see f_file_size_by_id()
+ * @see f_memory_array_increase_by()
+ */
+#ifndef _di_kt_tacocat_send_step_size_
+  extern void kt_tacocat_send_step_size(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // _di_kt_tacocat_send_step_size_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_send_step_size_h
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/wait.c b/sources/c/program/kevux/tools/tacocat/main/send/step/wait.c
new file mode 100644 (file)
index 0000000..77e81f7
--- /dev/null
@@ -0,0 +1,31 @@
+#include "../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_tacocat_send_step_wait_
+  f_status_t kt_tacocat_send_step_wait(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+    if (!main || !set || F_status_is_error(set->status)) return F_status_set_error(F_parameter);
+
+    // @todo process/validate the received response.
+
+    set->status = F_okay;
+
+    // When the buffer is smaller than the read block size, then the entire file should be completely sent.
+    if (set->size_done >= set->buffer.used) {
+      set->step = kt_tacocat_socket_step_send_done_e;
+
+      return F_complete;
+    }
+
+    set->step = kt_tacocat_socket_step_send_wait_e;
+
+    return F_complete_not;
+  }
+#endif // _di_kt_tacocat_send_step_wait_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sources/c/program/kevux/tools/tacocat/main/send/step/wait.h b/sources/c/program/kevux/tools/tacocat/main/send/step/wait.h
new file mode 100644 (file)
index 0000000..eecac75
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides send step wait functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_send_step_wait_h
+#define _kt_tacocat_send_step_wait_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the wait step of a send request.
+ *
+ * This prints on error.
+ *
+ * @param main
+ *   The main program and settings data.
+ *
+ *   Must not be NULL.
+ *
+ *   This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ *   The socket set to process.
+ *
+ *   Must not be NULL.
+ *
+ *   This alters set.status:
+ *     F_okay on success.
+ *
+ * @return
+ *     F_complete on success and entire payload is sent.
+ *     F_complete_not on success and the payload is not entirely sent.
+ *
+ *   F_parameter (with error bit) on invalid parameter.
+ */
+#ifndef _di_kt_tacocat_send_step_wait_
+  extern f_status_t kt_tacocat_send_step_wait(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // _di_kt_tacocat_send_step_wait_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_send_step_wait_h
index 157124d355c99e19bde921c609981504f6d6d169..71d8426849f0bd9c417fab0b3ab22d1d7e741092 100644 (file)
 #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/send/step/build.h>
+#include <program/kevux/tools/tacocat/main/send/step/check.h>
+#include <program/kevux/tools/tacocat/main/send/step/done.h>
+#include <program/kevux/tools/tacocat/main/send/step/encode.h>
+#include <program/kevux/tools/tacocat/main/send/step/file.h>
+#include <program/kevux/tools/tacocat/main/send/step/header.h>
+#include <program/kevux/tools/tacocat/main/send/step/packet.h>
+#include <program/kevux/tools/tacocat/main/send/step/size.h>
+#include <program/kevux/tools/tacocat/main/send/step/wait.h>
 #include <program/kevux/tools/tacocat/main/signal.h>
 #include <program/kevux/tools/tacocat/main/thread.h>