From ae416e87d9f3239f02c47df7f3fbaf73de0aaa03 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Tue, 16 Jan 2024 18:01:39 -0600 Subject: [PATCH] Progress: Further work in TacocaT. This strongly moves in the direction of setting up sending and receiving the different packets. This includes handling of multiple packet parts. None of this is ready yet, but progress is being made. There is currently a strong focus on getting the FSS Payload processing code wrapped up, working, and tested. --- data/build/tacocat/dependencies | 3 + data/build/tacocat/settings | 7 +- sources/c/tacocat/main/common/define.h | 24 +- sources/c/tacocat/main/common/enumeration.h | 22 +- sources/c/tacocat/main/common/print.c | 1 + sources/c/tacocat/main/common/print.h | 1 + sources/c/tacocat/main/common/type.c | 4 + sources/c/tacocat/main/common/type.h | 20 +- sources/c/tacocat/main/packet.c | 335 +++++++++++++++++++++++ sources/c/tacocat/main/packet.h | 119 ++++++++ sources/c/tacocat/main/print/error.c | 6 +- sources/c/tacocat/main/process.c | 9 +- sources/c/tacocat/main/receive.c | 407 +++++----------------------- sources/c/tacocat/main/receive.h | 82 +----- sources/c/tacocat/main/send.c | 176 +++++++++--- sources/c/tacocat/main/send.h | 37 ++- sources/c/tacocat/main/tacocat.h | 1 + 17 files changed, 755 insertions(+), 499 deletions(-) create mode 100644 sources/c/tacocat/main/packet.c create mode 100644 sources/c/tacocat/main/packet.h diff --git a/data/build/tacocat/dependencies b/data/build/tacocat/dependencies index 9bc3c9a..eb5d088 100644 --- a/data/build/tacocat/dependencies +++ b/data/build/tacocat/dependencies @@ -6,6 +6,7 @@ f_memory f_type_array f_string f_utf +f_abstruse f_color f_console f_compare @@ -13,10 +14,12 @@ f_conversion f_file f_fss f_network +f_parse f_path f_pipe f_print f_random +f_rip f_signal f_socket f_status_string diff --git a/data/build/tacocat/settings b/data/build/tacocat/settings index 32f4e41..82a4dc2 100644 --- a/data/build/tacocat/settings +++ b/data/build/tacocat/settings @@ -34,14 +34,14 @@ build_language c build_libraries -lc build_libraries-individual -lfll_error -lfll_fss -lfll_print -lfll_program build_libraries-individual -lfl_conversion -lfl_fss -lfl_print -lfl_status_string -build_libraries-individual -lf_color -lf_compare -lf_console -lf_conversion -lf_file -lf_fss -lf_memory -lf_network -lf_path -lf_pipe -lf_print -lf_random -lf_signal -lf_socket -lf_status_string -lf_string -lf_time -lf_type_array -lf_utf +build_libraries-individual -lf_abstruse -lf_color -lf_compare -lf_console -lf_conversion -lf_file -lf_fss -lf_memory -lf_network -lf_parse -lf_path -lf_pipe -lf_print -lf_random -lf_rip -lf_signal -lf_socket -lf_status_string -lf_string -lf_time -lf_type_array -lf_utf build_libraries-individual_thread -lf_thread build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library main/common.c main/common/define.c main/common/enumeration.c main/common/print.c main/common/string.c main/common/type.c main/print/error.c main/print/message.c main/print/verbose.c main/print/warning.c main/process.c main/receive.c main/send.c main/signal.c main/tacocat.c main/thread.c +build_sources_library main/common.c main/common/define.c main/common/enumeration.c main/common/print.c main/common/string.c main/common/type.c main/print/error.c main/print/message.c main/print/verbose.c main/print/warning.c main/packet.c main/process.c main/receive.c main/send.c main/signal.c main/tacocat.c main/thread.c -build_sources_headers main/common.h main/common/define.h main/common/enumeration.h main/common/print.h main/common/string.h main/common/type.h main/print/error.h main/print/message.h main/print/verbose.h main/print/warning.h main/process.h main/receive.h main/send.h main/signal.h main/tacocat.h main/thread.h +build_sources_headers main/common.h main/common/define.h main/common/enumeration.h main/common/print.h main/common/string.h main/common/type.h main/print/error.h main/print/message.h main/print/verbose.h main/print/warning.h main/packet.h main/process.h main/receive.h main/send.h main/signal.h main/tacocat.h main/thread.h build_sources_program main/main.c @@ -77,6 +77,7 @@ environment LANG LC_ALL LC_COLLATE LC_CTYPE LC_FASTMSG LC_MESSAGES LC_MONETARY L defines -D_libcap_legacy_only_ defines-threadless -D_di_thread_support_ defines-thread -D_pthread_attr_unsupported_ -D_pthread_sigqueue_unsupported_ +defines-individual_thread -D_pthread_attr_unsupported_ -D_pthread_sigqueue_unsupported_ flags -O2 -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-parentheses -Wno-missing-braces flags-thread -pthread diff --git a/sources/c/tacocat/main/common/define.h b/sources/c/tacocat/main/common/define.h index ce1c6a0..6b23bbb 100644 --- a/sources/c/tacocat/main/common/define.h +++ b/sources/c/tacocat/main/common/define.h @@ -43,6 +43,7 @@ extern "C" { * * kt_tacocat_packet_*_d: * - headers: The number of header Objects in the abstruse to create for sending a packet (type, name, part, size, status, and total). + * - id_length: The length used to generate the random string for the transaction ID (must be less than 2^8, aka less than 256). * - minimum: The minimum packet size, "header:\npayload:\n" = 17. * - peek: The size to peek into the packet to get the initial information. * - prebuffer: A size used to include during allocation to add additional space for the packet header and therefore help reduce the potential number of allocations. @@ -66,7 +67,7 @@ extern "C" { #define kt_tacocat_allocation_large_d 0x800 #define kt_tacocat_allocation_small_d 0x80 - #define kt_tacocat_block_size_d 0xffff // @todo set this to something small like 0xff to easily test and design sending and receiving multiple parts. + #define kt_tacocat_block_size_d 0xffff #define kt_tacocat_block_size_receive_d kt_tacocat_block_size_d #define kt_tacocat_block_size_send_d kt_tacocat_block_size_d @@ -79,7 +80,8 @@ extern "C" { #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 0x7 + #define kt_tacocat_packet_headers_d 0x8 + #define kt_tacocat_packet_id_length_d 0x20 #define kt_tacocat_packet_minimum_d 0x11 #define kt_tacocat_packet_peek_d 0x40 #define kt_tacocat_packet_prebuffer_d 0x200 @@ -113,9 +115,6 @@ extern "C" { * Intended to be used for handling an error during the receive process while not processing within step kt_tacocat_socket_step_receive_control_e. * The parameter id_data and is set to 0 to disable and is otherwise an address pointer. * - * macro_kt_receive_process_handle_error_exit_2: - * A version of macro_kt_receive_process_handle_error_exit_1 that uses a void return statement. - * * macro_kt_receive_process_begin_handle_error_exit_1: * Intended to be used for handling an error during the receive process while processing within step kt_tacocat_socket_step_receive_control_e. * @@ -175,7 +174,7 @@ extern "C" { kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(method), kt_tacocat_receive_s, network, status, name); \ \ if (id_data) { \ - f_file_close_id(id_data); \ + f_file_close_id(&(id_data)); \ } \ \ step = 0; \ @@ -183,19 +182,6 @@ extern "C" { return F_done_not; \ } - #define macro_kt_receive_process_handle_error_exit_2(main, method, network, status, name, step, id_data) \ - if (F_status_is_error(status)) { \ - kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(method), kt_tacocat_receive_s, network, status, name); \ - \ - if (id_data) { \ - f_file_close_id(id_data); \ - } \ - \ - step = 0; \ - \ - return; \ - } - #define macro_kt_receive_process_begin_handle_error_exit_1(main, method, network, status, name, step) \ if (F_status_is_error(status)) { \ kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(method), kt_tacocat_receive_s, network, status, name); \ diff --git a/sources/c/tacocat/main/common/enumeration.h b/sources/c/tacocat/main/common/enumeration.h index bf6181c..d66f281 100644 --- a/sources/c/tacocat/main/common/enumeration.h +++ b/sources/c/tacocat/main/common/enumeration.h @@ -181,6 +181,7 @@ extern "C" { * - extract: Process the loaded data, extracting the Header and Signature sections. * - check: Check the loaded data, doing size checks, interpreting the status, and performing any signature checks. * - write: Save the loaded Payload block to the file (write to the file). + * - next: Send "next" or "done" packet. * - done: Done processing file. */ #ifndef _di_kt_tacocat_socket_step_receive_e_ @@ -192,6 +193,7 @@ extern "C" { kt_tacocat_socket_step_receive_extract_e, kt_tacocat_socket_step_receive_check_e, kt_tacocat_socket_step_receive_write_e, + kt_tacocat_socket_step_receive_next_e, kt_tacocat_socket_step_receive_done_e, }; // enum #endif // _di_kt_tacocat_socket_step_receive_e_ @@ -200,15 +202,16 @@ extern "C" { * Individual socket-specific steps for receiving. * * kt_tacocat_socket_step_send_*_e: - * - none: No flags set. - * - size: Determine the file size. - * - header: Build and buffer the header. - * - build: Build the header information. - * - file: Buffer the file. - * - check: Additional checks before sending, such as re-checking header size. - * - encode: Encode entire packet. - * - packet: Send the entire packet. - * - done: The entire Packet is sent. + * - none: No flags set. + * - size: Determine the file size. + * - header: Build and buffer the header. + * - build: Build the header information. + * - file: Buffer the file. + * - check: Additional checks before sending, such as re-checking header size. + * - encode: Encode entire packet. + * - packet: Send the packet. + * - response: Wait for a response packet from the opposite end. + * - done: The entire Packet is sent. */ #ifndef _di_kt_tacocat_socket_step_send_e_ enum { @@ -220,6 +223,7 @@ extern "C" { kt_tacocat_socket_step_send_check_e, kt_tacocat_socket_step_send_encode_e, kt_tacocat_socket_step_send_packet_e, + kt_tacocat_socket_step_send_wait_e, kt_tacocat_socket_step_send_done_e, }; // enum #endif // _di_kt_tacocat_socket_step_send_e_ diff --git a/sources/c/tacocat/main/common/print.c b/sources/c/tacocat/main/common/print.c index 61ab7a6..664e5e6 100644 --- a/sources/c/tacocat/main/common/print.c +++ b/sources/c/tacocat/main/common/print.c @@ -47,6 +47,7 @@ extern "C" { "fll_program_parameter_process_verbosity", "kt_tacocat_process_abstruse_initialize", "kt_tacocat_process_socket_set_error_has", + "kt_tacocat_send_process_initialize", "kt_tacocat_setting_load_address_port_extract", "kt_tacocat_setting_load_send_receive_allocate", }; diff --git a/sources/c/tacocat/main/common/print.h b/sources/c/tacocat/main/common/print.h index 7b4d566..f275829 100644 --- a/sources/c/tacocat/main/common/print.h +++ b/sources/c/tacocat/main/common/print.h @@ -80,6 +80,7 @@ extern "C" { kt_tacocat_f_fll_program_parameter_process_verbosity_e, kt_tacocat_f_kt_tacocat_process_abstruse_initialize_e, kt_tacocat_f_kt_tacocat_process_socket_set_error_has_e, + kt_tacocat_f_kt_tacocat_send_process_initialize_e, kt_tacocat_f_kt_tacocat_setting_load_address_port_extract_e, kt_tacocat_f_kt_tacocat_setting_load_send_receive_allocate_e, }; // enum diff --git a/sources/c/tacocat/main/common/type.c b/sources/c/tacocat/main/common/type.c index de254be..b72d1dc 100644 --- a/sources/c/tacocat/main/common/type.c +++ b/sources/c/tacocat/main/common/type.c @@ -138,6 +138,10 @@ extern "C" { f_memory_array_resize(0, sizeof(f_char_t), (void **) &array[i].header.string, &array[i].header.used, &array[i].header.size); } + if (array[i].id.size) { + f_memory_array_resize(0, sizeof(f_char_t), (void **) &array[i].id.string, &array[i].id.used, &array[i].id.size); + } + if (array[i].name.size) { f_memory_array_resize(0, sizeof(f_char_t), (void **) &array[i].name.string, &array[i].name.used, &array[i].name.size); } diff --git a/sources/c/tacocat/main/common/type.h b/sources/c/tacocat/main/common/type.h index ec3a04d..5f8e838 100644 --- a/sources/c/tacocat/main/common/type.h +++ b/sources/c/tacocat/main/common/type.h @@ -23,9 +23,11 @@ extern "C" { * size_done: The size in bytes that are done being processed (generally used by send/write). * size_total: The size in bytes tht represent the entire size to be processed (size_done should eventually equal this). * - * flag: A set of flags. - * step: The current step the socket set is operating under. - * retry: The current number of retries performed. + * flag: A set of flags. + * step: The current step the socket set is operating under. + * retry: The current number of retries performed. + * part: The current active part number. + * * file: The file structure. * socket: Socket structure. * status: The status of the socket operations. @@ -72,6 +74,8 @@ extern "C" { uint16_t flag; uint16_t step; uint16_t retry; + f_number_unsigned_t part; + f_file_t file; f_socket_t socket; f_status_t status; @@ -101,10 +105,11 @@ extern "C" { f_string_dynamic_t cache; f_string_dynamic_t client; f_string_dynamic_t header; + f_string_dynamic_t id; f_string_dynamic_t name; f_string_dynamic_t network; f_fss_simple_packet_range_t packet; - f_fss_payload_header_write_state_t write_state; + f_fss_payload_header_state_t write_state; f_abstruse_maps_t abstruses; f_string_maps_t headers; @@ -144,8 +149,9 @@ 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, \ - f_fss_payload_header_write_state_t_initialize, \ + f_fss_payload_header_state_t_initialize, \ f_abstruse_maps_t_initialize, \ f_string_maps_t_initialize, \ } @@ -185,8 +191,9 @@ 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, \ - f_fss_payload_header_write_state_t_initialize, \ + f_fss_payload_header_state_t_initialize, \ f_abstruse_maps_t_initialize, \ f_string_maps_t_initialize, \ } @@ -226,6 +233,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, \ diff --git a/sources/c/tacocat/main/packet.c b/sources/c/tacocat/main/packet.c new file mode 100644 index 0000000..2dce22c --- /dev/null +++ b/sources/c/tacocat/main/packet.c @@ -0,0 +1,335 @@ +#include "tacocat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_kt_tacocat_packet_extract_ + void kt_tacocat_packet_extract(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set, const f_string_static_t direction) { + + if (!main || !set) return; + + kt_tacocat_process_abstruse_initialize(main, set); + + if (F_status_is_error(set->status)) { + kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(kt_tacocat_process_abstruse_initialize), direction, set->network, set->status, set->name); + + if (set->socket.id_data) { + f_file_close_id(&set->socket.id_data); + } + + set->step = 0; + + return; + } + + // 0x1 = did not find payload, 0x2 = did not find header. + uint8_t found_not = 0x3; + + for (f_number_unsigned_t i = 0; i < set->objects.used; ++i) { + + if (f_compare_dynamic_partial_string(f_fss_payload_object_header_s.string, set->buffer, f_fss_payload_object_header_s.used, set->objects.array[i]) == F_equal_to) { + kt_tacocat_packet_extract_header(main, set, i, direction); + + if (F_status_is_error(set->status)) { + // @todo handle F_packet error, setup the sending of an invalid packet response (things similar to this needs to be done in multiple places). + ++set->retry; + + return; + } + + found_not &= ~0x2; + } + else if (f_compare_dynamic_partial_string(f_fss_payload_object_signature_s.string, set->buffer, f_fss_payload_object_signature_s.used, set->objects.array[i]) == F_equal_to) { + kt_tacocat_packet_extract_signature(main, set, i, direction); + + if (F_status_is_error(set->status)) { + ++set->retry; + + return; + } + } + else if (f_compare_dynamic_partial_string(f_fss_payload_object_payload_s.string, set->buffer, f_fss_payload_object_payload_s.used, set->objects.array[i]) == F_equal_to) { + if (found_not & 0x1) { + set->packet.payload = set->contents.array[i].array[0]; + found_not &= ~0x1; + } + } + } // for + + set->status = F_okay; + } +#endif // _di_kt_tacocat_packet_extract_ + +#ifndef _di_kt_tacocat_packet_extract_header_ + void kt_tacocat_packet_extract_header(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set, const f_number_unsigned_t at, const f_string_static_t direction) { + + if (!main || !set) return; + + if (set->objects.array[at].start > set->objects.array[at].stop || !set->contents.array[at].used) { + set->status = F_data_not; + + return; + } + + set->range = set->contents.array[at].array[0]; + + fll_fss_extended_read(set->buffer, &set->range, &set->objects_header, &set->contents_header, &set->objects_quoted_header, &set->contents_quoted_header, &set->objects_delimits_header, &set->contents_delimits_header, &set->state); + + if (F_status_is_error(set->state.status)) { + kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(fll_fss_extended_read), direction, set->network, set->status, set->name); + + set->status = set->state.status; + + return; + } + + switch (set->state.status) { + case F_okay: + case F_okay_stop: + case F_okay_eos: + break; + + default: + set->status = F_data_not; + + return; + } + + 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]; + } + + // 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) { + + // Require Content to exist. + if (!set->contents_header.array[i].used) { + set->abstruses.array[6].value.type = f_abstruse_none_e; + + continue; + } + + 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]; + } + + // 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[7].value.type = f_abstruse_none_e; + + 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 + + // Convert the status code. + if (set->abstruses.array[0].value.type) { + const f_number_unsigned_t length = set->abstruses.array[0].value.is.a_range.stop - set->abstruses.array[0].value.is.a_range.start + 1; + char buffer[length]; + f_status_t status = F_false; + + memcpy(buffer, set->buffer.string + set->abstruses.array[0].value.is.a_range.start, length); + + const f_string_static_t status_string = macro_f_string_static_t_initialize_1(buffer, 0, length); + + set->status = fl_status_string_from(status_string, &status); + + if (set->status == F_okay) { + set->abstruses.array[0].value.type = f_abstruse_unsigned_e; + set->abstruses.array[0].value.is.a_unsigned = (f_number_unsigned_t) status; + } + else { + kt_tacocat_print_error_on_packet_header_value_invalid(&main->program.error, direction, set->network, set->status, set->name, set->buffer, set->objects.array[at], set->abstruses.array[6].value.is.a_range); + + set->abstruses.array[0].value.type = f_abstruse_none_e; + set->abstruses.array[0].value.is.a_unsigned = 0; + + set->status = F_status_set_error(F_packet); + } + } + + // Convert the type. + if (set->abstruses.array[1].value.type) { + if (f_compare_dynamic_partial_string(kt_tacocat_file_s.string, set->buffer, kt_tacocat_file_s.used, set->abstruses.array[1].value.is.a_range) == F_equal_to) { + set->abstruses.array[1].value.type = f_abstruse_unsigned_e; + set->abstruses.array[1].value.is.a_unsigned = (f_number_unsigned_t) kt_tacocat_packet_type_file_e; + } + else if (f_compare_dynamic_partial_string(kt_tacocat_done_s.string, set->buffer, kt_tacocat_done_s.used, set->abstruses.array[1].value.is.a_range) == F_equal_to) { + set->abstruses.array[1].value.type = f_abstruse_unsigned_e; + set->abstruses.array[1].value.is.a_unsigned = (f_number_unsigned_t) kt_tacocat_packet_type_done_e; + } + else if (f_compare_dynamic_partial_string(kt_tacocat_next_s.string, set->buffer, kt_tacocat_next_s.used, set->abstruses.array[1].value.is.a_range) == F_equal_to) { + set->abstruses.array[1].value.type = f_abstruse_unsigned_e; + set->abstruses.array[1].value.is.a_unsigned = (f_number_unsigned_t) kt_tacocat_packet_type_next_e; + } + else if (f_compare_dynamic_partial_string(kt_tacocat_resend_s.string, set->buffer, kt_tacocat_resend_s.used, set->abstruses.array[1].value.is.a_range) == F_equal_to) { + set->abstruses.array[1].value.type = f_abstruse_unsigned_e; + set->abstruses.array[1].value.is.a_unsigned = (f_number_unsigned_t) kt_tacocat_packet_type_resend_e; + } + else { + set->status = F_status_set_error(F_found_not); + + kt_tacocat_print_error_on_packet_header_value_invalid(&main->program.error, direction, set->network, set->status, set->name, set->buffer, set->objects.array[at], set->abstruses.array[6].value.is.a_range); + + set->abstruses.array[1].value.type = f_abstruse_none_e; + set->abstruses.array[1].value.is.a_unsigned = 0; + + set->status = F_status_set_error(F_packet); + + return; + } + } + + // Convert the length, part, and total. + { + f_number_unsigned_t number = 0; + + for (i = 2; i < 5; ++i) { + + if (!set->abstruses.array[i].value.type) continue; + + set->status = fl_conversion_dynamic_partial_to_unsigned(fl_conversion_data_base_10_c, set->buffer, set->abstruses.array[i].value.is.a_range, &number); + + if (set->status == F_okay) { + set->abstruses.array[i].value.type = f_abstruse_unsigned_e; + set->abstruses.array[i].value.is.a_unsigned = number; + } + else { + kt_tacocat_print_error_on_packet_header_value_invalid(&main->program.error, direction, set->network, set->status, set->name, set->buffer, set->objects.array[at], set->abstruses.array[6].value.is.a_range); + + set->abstruses.array[i].value.type = f_abstruse_none_e; + set->abstruses.array[i].value.is.a_unsigned = 0; + + set->status = F_status_set_error(F_packet); + } + } // for + } + + set->abstruses.used = kt_tacocat_packet_headers_d; + set->status = F_okay; + } +#endif // _di_kt_tacocat_packet_extract_header_ + +#ifndef _di_kt_tacocat_packet_extract_signature_ + void kt_tacocat_packet_extract_signature(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set, const f_number_unsigned_t at, const f_string_static_t direction) { + + if (!main || !set) return; + + if (set->objects.array[at].start > set->objects.array[at].stop || !set->contents.array[at].used) { + set->status = F_data_not; + + return; + } + + set->range = set->contents.array[at].array[0]; + + fll_fss_extended_read(set->buffer, &set->range, &set->objects_signature, &set->contents_signature, &set->objects_quoted_header, &set->contents_quoted_header, &set->objects_delimits_signature, &set->contents_delimits_signature, &set->state); + + if (F_status_is_error(set->state.status)) { + kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(fll_fss_extended_read), direction, set->network, set->status, set->name); + + set->status = set->state.status; + + return; + } + + // @todo maybe index 8 and beyond in the abstruse shall represent signatures? + + set->status = F_okay; + } +#endif // _di_kt_tacocat_packet_extract_signature_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/sources/c/tacocat/main/packet.h b/sources/c/tacocat/main/packet.h new file mode 100644 index 0000000..13ce42e --- /dev/null +++ b/sources/c/tacocat/main/packet.h @@ -0,0 +1,119 @@ +/** + * Kevux Tools - TacocaT + * + * Project: Kevux Tools + * API Version: 0.5 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _kt_tacocat_packet_h +#define _kt_tacocat_packet_h + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Process the header and signature strings, extracting the data. + * + * Another function should perform some of the validation on the header. + * @todo This other function needs to return a status code such as F_continue to designate to continue to the next iteration. + * Ideally, the flag will be set to how to continue, such as "continue loading the entire payload". + * This situation would arise when the payload needs to be validated, such as the size. + * + * @param main + * The main program and settings data. + * + * 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_memory_array_increase_by(). + * Errors (with error bit) from: kt_tacocat_packet_extract_header(). + * Errors (with error bit) from: kt_tacocat_packet_extract_signature(). + * @param direction + * The string representing the direction and is used for error handling. + * This is generally either kt_tacocat_receive_s or kt_tacocat_send_s. + * + * @see f_memory_array_increase_by() + * @see kt_tacocat_packet_extract_header() + * @see kt_tacocat_packet_extract_signature() + */ +#ifndef _di_kt_tacocat_packet_extract_ + extern void kt_tacocat_packet_extract(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set, const f_string_static_t direction); +#endif // _di_kt_tacocat_packet_extract_ + +/** + * Extract the header strings using the given index for an Object and Content. + * + * The positions in the abstruse are hard-coded with specific representations. + * + * Index Positions: + * - 0: Status string (such as F_okay). + * - 1: Type string (type of packet). + * - 2: Length number (the length of the Payload section). + * - 3: Packet part number. + * - 4: Total packet parts number. + * - 5: Name string (file name). + * - 6: Salt string (for making packet unique, if encrypted, signed, or something similar). + * - 7: Transaction ID (Can be anything, generally unique or port number). + * + * @param main + * The main program and settings data. + * + * 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_data_not on success, but no data to process. + * + * F_packet (with error bit) on invalid packet header. + * + * Errors (with error bit) from: fll_fss_extended_read(). + * @param at + * The index position representing which Object and Contents set to use. + * @param direction + * The string representing the direction and is used for error handling. + * This is generally either kt_tacocat_receive_s or kt_tacocat_send_s. + * + * @see fll_fss_extended_read() + */ +#ifndef _di_kt_tacocat_packet_extract_header_ + extern void kt_tacocat_packet_extract_header(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set, const f_number_unsigned_t at, const f_string_static_t direction); +#endif // _di_kt_tacocat_packet_extract_header_ + +/** + * Extract the signature strings using the given index for an Object and Content. + * + * @param main + * The main program and settings data. + * + * 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. + * @param direction + * The string representing the direction and is used for error handling. + * This is generally either kt_tacocat_receive_s or kt_tacocat_send_s. + * @param at + * The index position representing which Object and Contents set to use. + */ +#ifndef _di_kt_tacocat_packet_extract_signature_ + extern void kt_tacocat_packet_extract_signature(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set, const f_number_unsigned_t at, const f_string_static_t direction); +#endif // _di_kt_tacocat_packet_extract_signature_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _kt_tacocat_packet_h diff --git a/sources/c/tacocat/main/print/error.c b/sources/c/tacocat/main/print/error.c index f0802de..1452342 100644 --- a/sources/c/tacocat/main/print/error.c +++ b/sources/c/tacocat/main/print/error.c @@ -169,9 +169,9 @@ extern "C" { fl_print_format("%[' with file '%]", print->to, print->set->error, print->set->error, f_string_eol_s); fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, name, print->set->notable); fl_print_format("%[' is invalid for Object '%]", print->to, print->set->error, print->set->error, f_string_eol_s); - fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, buffer, object, print->set->notable); + fl_print_format(f_string_format_Q_range_single_s.string, print->to, print->set->notable, buffer, object, print->set->notable); fl_print_format("%[' and Content '%]", print->to, print->set->error, print->set->error, f_string_eol_s); - fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, buffer, content, print->set->notable); + fl_print_format(f_string_format_Q_range_single_s.string, print->to, print->set->notable, buffer, content, print->set->notable); fl_print_format("%[' with a status code of %]", print->to, print->set->error, print->set->error, f_string_eol_s); fl_print_format(f_string_format_ul_single_s.string, print->to, print->set->notable, status, print->set->notable); fl_print_format("%[.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); @@ -337,7 +337,7 @@ extern "C" { f_file_stream_lock(print->to); fl_print_format("%[%QUnknown or invalid port number%] ", print->to, print->set->error, print->prefix, print->set->error); - fl_print_format("%[%/Q%]", print->to, print->set->notable, address, range, print->set->notable); + fl_print_format(f_string_format_Q_range_single_s.string, print->to, print->set->notable, address, range, print->set->notable); fl_print_format(" %[from the address '%]", print->to, print->set->error, print->set->error, f_string_eol_s); fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, address, print->set->notable); fl_print_format("%['.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s); diff --git a/sources/c/tacocat/main/process.c b/sources/c/tacocat/main/process.c index 63b1750..c5d3a59 100644 --- a/sources/c/tacocat/main/process.c +++ b/sources/c/tacocat/main/process.c @@ -96,11 +96,18 @@ extern "C" { 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; + { long salt = 0; @@ -109,7 +116,7 @@ extern "C" { set->abstruses.array[6].value.is.a_unsigned = (f_number_unsigned_t) salt; } - set->abstruses.used = 7; + set->abstruses.used = kt_tacocat_packet_headers_d; } #endif // _di_kt_tacocat_process_abstruse_initialize_ diff --git a/sources/c/tacocat/main/receive.c b/sources/c/tacocat/main/receive.c index 84b0abc..b30600e 100644 --- a/sources/c/tacocat/main/receive.c +++ b/sources/c/tacocat/main/receive.c @@ -28,7 +28,7 @@ extern "C" { } // Skip if status from poll is an error or is F_time_out. - if (main->setting.active_receive >> main->setting.status_receive == F_okay) { + if (main->setting.active_receive || main->setting.status_receive == F_okay) { for (i = 0; i < main->setting.receive_polls.used; ++i) { if (main->setting.receive_polls.array[i].fd == -1) continue; @@ -107,32 +107,7 @@ extern "C" { if (!(set->step)) { kt_tacocat_print_message_receive_operation_received(&main->program.message, *set); - set->abstruses.used = 0; - set->buffer.used = 0; - set->cache.used = 0; - set->header.used = 0; - set->headers.used = 0; - set->objects.used = 0; - set->contents.used = 0; - set->objects_delimits.used = 0; - set->contents_delimits.used = 0; - set->comments.used = 0; - set->retry = 0; - set->size_done = 0; - set->size_total = 0; - set->file.size_read = set->size_block; - set->socket.size_read = kt_tacocat_packet_read_d; - set->socket.id_data = -1; - set->range.start = 1; - set->range.stop = 0; - set->state.status = F_none; - set->status = F_none; - set->packet.control = 0; - set->packet.size = 0; - set->packet.payload.start = 1; - set->packet.payload.stop = 0; - set->step = kt_tacocat_socket_step_receive_control_e; - set->flag = 0; + kt_tacocat_receive_process_initialize(main, set); ++main->setting.active_receive; } @@ -170,7 +145,7 @@ extern "C" { // Make sure the buffer is large enough for payload processing block reads. set->status = f_memory_array_increase_by(set->socket.size_read, sizeof(f_char_t), (void **) &set->buffer.string, &set->buffer.used, &set->buffer.size); - macro_kt_receive_process_handle_error_exit_1(main, f_memory_array_increase_by, set->network, set->status, set->name, set->flag, &set->socket.id_data); + macro_kt_receive_process_handle_error_exit_1(main, f_memory_array_increase_by, set->network, set->status, set->name, set->flag, set->socket.id_data); set->retry = 0; set->buffer.used = 0; @@ -181,7 +156,7 @@ extern "C" { size_t length_read = 0; set->status = f_socket_read_stream(&set->socket, 0, (void *) (set->buffer.string + set->buffer.used), &length_read); - macro_kt_receive_process_handle_error_exit_1(main, f_socket_read_stream, set->network, set->status, set->name, set->flag, &set->socket.id_data); + macro_kt_receive_process_handle_error_exit_1(main, f_socket_read_stream, set->network, set->status, set->name, set->flag, set->socket.id_data); if (length_read) { set->retry = 0; @@ -277,14 +252,39 @@ extern "C" { } if (set->step == kt_tacocat_socket_step_receive_extract_e) { - kt_tacocat_receive_process_extract(main, set); + kt_tacocat_packet_extract(main, set, kt_tacocat_receive_s); if (F_status_is_error(set->status)) return F_data_not; - set->step = kt_tacocat_socket_step_receive_write_e; + set->step = kt_tacocat_socket_step_receive_check_e; } if (set->step == kt_tacocat_socket_step_receive_check_e) { - // @todo + if (set->parts.used) { + // @todo determine type of packet and process. + } + else { + // @todo the packet should only be a 'file' type for the first packet. + if (set->abstruses.array[4].value.type == f_abstruse_unsigned_e) { + set->parts.used = 0; + + 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); + macro_kt_receive_process_handle_error_exit_1(main, f_memory_array_increase_by, set->network, set->status, set->name, set->flag, set->socket.id_data); + + memset(set->parts.array, 0, sizeof(f_number_unsigned_t)); + + set->parts.used = set->abstruses.array[4].value.is.a_unsigned; + } + else { + // @todo error. + } + + if (set->abstruses.array[3].value.type == f_abstruse_unsigned_e) { + set->part = set->abstruses.array[3].value.is.a_unsigned; + } + else { + // @todo error + } + } set->step = kt_tacocat_socket_step_receive_write_e; } @@ -310,6 +310,12 @@ extern "C" { f_file_close(&set->file); set->buffer.used = 0; + set->step = kt_tacocat_socket_step_receive_next_e; + } + + if (set->step == kt_tacocat_socket_step_receive_next_e) { + // @todo + set->step = kt_tacocat_socket_step_receive_done_e; } @@ -442,316 +448,41 @@ extern "C" { } #endif // _di_kt_tacocat_receive_process_control_ -#ifndef _di_kt_tacocat_receive_process_extract_ - void kt_tacocat_receive_process_extract(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) { +#ifndef _di_kt_tacocat_receive_process_initialize_ + void kt_tacocat_receive_process_initialize(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) { if (!main || !set) return; - kt_tacocat_process_abstruse_initialize(main, set); - - if (F_status_is_error(set->status)) { - macro_kt_receive_process_handle_error_exit_2(main, kt_tacocat_process_abstruse_initialize, set->network, set->status, set->name, set->step, &set->socket.id_data); - } - - // 0x1 = did not find payload, 0x2 = did not find header. - uint8_t found_not = 0x3; - - for (f_number_unsigned_t i = 0; i < set->objects.used; ++i) { - - if (f_compare_dynamic_partial_string(f_fss_payload_object_header_s.string, set->buffer, f_fss_payload_object_header_s.used, set->objects.array[i]) == F_equal_to) { - kt_tacocat_receive_process_extract_header(main, set, i); - - if (F_status_is_error(set->status)) { - // @todo handle F_packet error, setup the sending of an invalid packet response (things similar to this needs to be done in multiple places). - ++set->retry; - - return; - } - - found_not &= ~0x2; - } - else if (f_compare_dynamic_partial_string(f_fss_payload_object_signature_s.string, set->buffer, f_fss_payload_object_signature_s.used, set->objects.array[i]) == F_equal_to) { - kt_tacocat_receive_process_extract_signature(main, set, i); - - if (F_status_is_error(set->status)) { - ++set->retry; - - return; - } - } - else if (f_compare_dynamic_partial_string(f_fss_payload_object_payload_s.string, set->buffer, f_fss_payload_object_payload_s.used, set->objects.array[i]) == F_equal_to) { - if (found_not & 0x1) { - set->packet.payload = set->contents.array[i].array[0]; - found_not &= ~0x1; - } - } - } // for - - set->status = F_okay; - } -#endif // _di_kt_tacocat_receive_process_extract_ - -#ifndef _di_kt_tacocat_receive_process_extract_header_ - void kt_tacocat_receive_process_extract_header(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set, const f_number_unsigned_t at) { - - if (!main || !set) return; - - if (set->objects.array[at].start > set->objects.array[at].stop || !set->contents.array[at].used) { - set->status = F_data_not; - - return; - } - - set->range = set->contents.array[at].array[0]; - - fll_fss_extended_read(set->buffer, &set->range, &set->objects_header, &set->contents_header, &set->objects_quoted_header, &set->contents_quoted_header, &set->objects_delimits_header, &set->contents_delimits_header, &set->state); - - if (F_status_is_error(set->state.status)) { - kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(fll_fss_extended_read), kt_tacocat_receive_s, set->network, set->status, set->name); - - set->status = set->state.status; - - return; - } - - switch (set->state.status) { - case F_okay: - case F_okay_stop: - case F_okay_eos: - break; - - default: - set->status = F_data_not; - - return; - } - - 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].key = f_fss_payload_object_status_s; - 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].key = f_fss_payload_object_type_s; - 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].key = f_fss_payload_object_length_s; - 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].key = f_fss_payload_object_part_s; - 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].key = f_fss_payload_object_total_s; - 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].key = f_fss_payload_object_name_s; - 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]; - } - - // 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) { - - // Require Content to exist. - if (!set->contents_header.array[i].used) { - set->abstruses.array[6].value.type = f_abstruse_none_e; - - continue; - } - - set->abstruses.array[6].key = kt_tacocat_salt_s; - 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]; - } - } // for - - // Convert the status code. - if (set->abstruses.array[0].value.type) { - const f_number_unsigned_t length = set->abstruses.array[0].value.is.a_range.stop - set->abstruses.array[0].value.is.a_range.start + 1; - char buffer[length]; - f_status_t status = F_false; - - memcpy(buffer, set->buffer.string + set->abstruses.array[0].value.is.a_range.start, length); - - const f_string_static_t status_string = macro_f_string_static_t_initialize_1(buffer, 0, length); - - set->status = fl_status_string_from(status_string, &status); - - if (set->status == F_okay) { - set->abstruses.array[0].value.type = f_abstruse_unsigned_e; - set->abstruses.array[0].value.is.a_unsigned = (f_number_unsigned_t) status; - } - else { - kt_tacocat_print_error_on_packet_header_value_invalid(&main->program.error, kt_tacocat_receive_s, set->network, set->status, set->name, set->buffer, set->objects.array[at], set->abstruses.array[6].value.is.a_range); - - set->abstruses.array[0].value.type = f_abstruse_none_e; - set->abstruses.array[0].value.is.a_unsigned = 0; - - set->status = F_status_set_error(F_packet); - } - } - - // Convert the type. - if (set->abstruses.array[1].value.type) { - if (f_compare_dynamic_partial_string(kt_tacocat_file_s.string, set->buffer, kt_tacocat_file_s.used, set->abstruses.array[1].value.is.a_range) == F_equal_to) { - set->abstruses.array[1].value.type = f_abstruse_unsigned_e; - set->abstruses.array[1].value.is.a_unsigned = (f_number_unsigned_t) kt_tacocat_packet_type_file_e; - } - else if (f_compare_dynamic_partial_string(kt_tacocat_done_s.string, set->buffer, kt_tacocat_done_s.used, set->abstruses.array[1].value.is.a_range) == F_equal_to) { - set->abstruses.array[1].value.type = f_abstruse_unsigned_e; - set->abstruses.array[1].value.is.a_unsigned = (f_number_unsigned_t) kt_tacocat_packet_type_done_e; - } - else if (f_compare_dynamic_partial_string(kt_tacocat_next_s.string, set->buffer, kt_tacocat_next_s.used, set->abstruses.array[1].value.is.a_range) == F_equal_to) { - set->abstruses.array[1].value.type = f_abstruse_unsigned_e; - set->abstruses.array[1].value.is.a_unsigned = (f_number_unsigned_t) kt_tacocat_packet_type_next_e; - } - else if (f_compare_dynamic_partial_string(kt_tacocat_resend_s.string, set->buffer, kt_tacocat_resend_s.used, set->abstruses.array[1].value.is.a_range) == F_equal_to) { - set->abstruses.array[1].value.type = f_abstruse_unsigned_e; - set->abstruses.array[1].value.is.a_unsigned = (f_number_unsigned_t) kt_tacocat_packet_type_resend_e; - } - else { - set->status = F_status_set_error(F_found_not); - - kt_tacocat_print_error_on_packet_header_value_invalid(&main->program.error, kt_tacocat_receive_s, set->network, set->status, set->name, set->buffer, set->objects.array[at], set->abstruses.array[6].value.is.a_range); - - set->abstruses.array[1].value.type = f_abstruse_none_e; - set->abstruses.array[1].value.is.a_unsigned = 0; - - set->status = F_status_set_error(F_packet); - - return; - } - } - - // Convert the length, part, and total. - { - f_number_unsigned_t number = 0; - - for (i = 2; i < 5; ++i) { - - if (!set->abstruses.array[i].value.type) continue; - - set->status = fl_conversion_dynamic_partial_to_unsigned(fl_conversion_data_base_10_c, set->buffer, set->abstruses.array[i].value.is.a_range, &number); - - if (set->status == F_okay) { - set->abstruses.array[i].value.type = f_abstruse_unsigned_e; - set->abstruses.array[i].value.is.a_unsigned = number; - } - else { - kt_tacocat_print_error_on_packet_header_value_invalid(&main->program.error, kt_tacocat_receive_s, set->network, set->status, set->name, set->buffer, set->objects.array[at], set->abstruses.array[6].value.is.a_range); - - set->abstruses.array[i].value.type = f_abstruse_none_e; - set->abstruses.array[i].value.is.a_unsigned = 0; - - set->status = F_status_set_error(F_packet); - } - } // for - } - - set->abstruses.used = 6; - set->status = F_okay; - } -#endif // _di_kt_tacocat_receive_process_extract_header_ - -#ifndef _di_kt_tacocat_receive_process_extract_signature_ - void kt_tacocat_receive_process_extract_signature(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set, const f_number_unsigned_t at) { - - if (!main || !set) return; - - if (set->objects.array[at].start > set->objects.array[at].stop || !set->contents.array[at].used) { - set->status = F_data_not; - - return; - } - - set->range = set->contents.array[at].array[0]; - - fll_fss_extended_read(set->buffer, &set->range, &set->objects_signature, &set->contents_signature, &set->objects_quoted_header, &set->contents_quoted_header, &set->objects_delimits_signature, &set->contents_delimits_signature, &set->state); - - if (F_status_is_error(set->state.status)) { - kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(fll_fss_extended_read), kt_tacocat_receive_s, set->network, set->status, set->name); - - set->status = set->state.status; - - return; - } - - // @todo maybe 7 and beyond in the abstruse shall represent signatures? - - set->status = F_okay; + set->abstruses.used = 0; + set->buffer.used = 0; + set->cache.used = 0; + set->header.used = 0; + set->headers.used = 0; + set->objects.used = 0; + set->contents.used = 0; + set->objects_delimits.used = 0; + set->contents_delimits.used = 0; + set->comments.used = 0; + set->retry = 0; + set->size_done = 0; + set->size_total = 0; + set->file.size_read = set->size_block; + set->socket.size_read = kt_tacocat_packet_read_d; + set->socket.id_data = -1; + set->range.start = 1; + set->range.stop = 0; + set->state.status = F_none; + set->status = F_none; + set->packet.control = 0; + set->packet.size = 0; + set->packet.payload.start = 1; + set->packet.payload.stop = 0; + set->part = 0; + set->parts.used = 0; + set->step = kt_tacocat_socket_step_receive_control_e; + set->flag = 0; } -#endif // _di_kt_tacocat_receive_process_extract_signature_ +#endif // _di_kt_tacocat_receive_process_initialize_ #ifdef __cplusplus } // extern "C" diff --git a/sources/c/tacocat/main/receive.h b/sources/c/tacocat/main/receive.h index f9bd57e..b78e930 100644 --- a/sources/c/tacocat/main/receive.h +++ b/sources/c/tacocat/main/receive.h @@ -119,76 +119,7 @@ extern "C" { #endif // _di_kt_tacocat_receive_process_control_ /** - * Process the header and signature strings, extracting the data. - * - * Another function should perform some of the validation on the header. - * @todo This other function needs to return a status code such as F_continue to designate to continue to the next iteration. - * Ideally, the flag will be set to how to continue, such as "continue loading the entire payload". - * This situation would arise when the payload needs to be validated, such as the size. - * - * @param main - * The main program and settings data. - * - * 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_memory_array_increase_by(). - * Errors (with error bit) from: kt_tacocat_receive_process_extract_header(). - * Errors (with error bit) from: kt_tacocat_receive_process_extract_signature(). - * - * @see f_memory_array_increase_by() - * @see kt_tacocat_receive_process_extract_header() - * @see kt_tacocat_receive_process_extract_signature() - */ -#ifndef _di_kt_tacocat_receive_process_extract_ - extern void kt_tacocat_receive_process_extract(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set); -#endif // _di_kt_tacocat_receive_process_extract_ - -/** - * Extract the header strings using the given index for an Object and Content. - * - * The positions in the abstruse are hard-coded with specific representations. - * - * Index Positions: - * - 0: Status string (such as F_okay). - * - 1: Type string (type of packet). - * - 2: Length number (the length of the Payload section). - * - 3: Packet part number. - * - 4: Total packet parts number. - * - 5: Name string (file name). - * - 6: Salt string (for making packet unique, if encrypted, signed, or something similar). - * - * @param main - * The main program and settings data. - * - * 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_data_not on success, but no data to process. - * - * F_packet (with error bit) on invalid packet header. - * - * Errors (with error bit) from: fll_fss_extended_read(). - * @param at - * The index position representing which Object and Contents set to use. - * - * @see fll_fss_extended_read() - */ -#ifndef _di_kt_tacocat_receive_process_extract_header_ - extern void kt_tacocat_receive_process_extract_header(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set, const f_number_unsigned_t at); -#endif // _di_kt_tacocat_receive_process_extract_header_ - -/** - * Extract the signature strings using the given index for an Object and Content. + * Process the network socket, performing the initialization step such as when step == 0. * * @param main * The main program and settings data. @@ -198,14 +129,11 @@ extern "C" { * The socket set to process. * Must not be NULL. * - * This alters set.status: - * F_okay on success. - * @param at - * The index position representing which Object and Contents set to use. + * This does not alter set.status. */ -#ifndef _di_kt_tacocat_receive_process_extract_signature_ - extern void kt_tacocat_receive_process_extract_signature(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set, const f_number_unsigned_t at); -#endif // _di_kt_tacocat_receive_process_extract_signature_ +#ifndef _di_kt_tacocat_receive_process_initialize_ + extern void kt_tacocat_receive_process_initialize(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set); +#endif // _di_kt_tacocat_receive_process_initialize_ #ifdef __cplusplus } // extern "C" diff --git a/sources/c/tacocat/main/send.c b/sources/c/tacocat/main/send.c index e8aa708..5c03e8c 100644 --- a/sources/c/tacocat/main/send.c +++ b/sources/c/tacocat/main/send.c @@ -14,6 +14,7 @@ extern "C" { kt_tacocat_main_t * const main = (kt_tacocat_main_t *) void_main; f_number_unsigned_t i = 0; f_status_t ready = F_okay; + bool poll = F_false; kt_tacocat_process_socket_set_send(main); @@ -51,11 +52,27 @@ extern "C" { ++main->setting.send.array[i].retry; } + if (main->setting.send.array[i].step == kt_tacocat_socket_step_send_wait_e) { + poll = F_true; + } + ready = F_done_not; } } } // for + if (F_status_is_error_not(main->setting.status_send) && poll) { + main->setting.status_send = f_file_poll(main->setting.send_polls, main->setting.active_send ? main->setting.interval_fast : main->setting.interval); + + if (main->program.signal_received) { + main->setting.status_receive = F_status_set_error(F_interrupt); + + return 0; + } + + poll = F_false; + } + } while (F_status_is_error_not(main->setting.status_send) && ready == F_done_not); } @@ -77,44 +94,10 @@ extern "C" { if (!main || !set) return F_status_set_error(F_parameter); if (!set->step) { - set->abstruses.used = 0; - set->buffer.used = 0; - set->cache.used = 0; - set->header.used = 0; - set->headers.used = 0; - set->objects.used = 0; - set->contents.used = 0; - set->objects_delimits.used = 0; - set->contents_delimits.used = 0; - set->comments.used = 0; - set->retry = 0; - set->size_done = 0; - set->size_total = 0; - set->file.size_read = set->size_block; - set->socket.size_read = kt_tacocat_packet_read_d; - set->range.start = -1; - set->range.stop = 0; - set->packet.control = 0; - set->packet.size = 0; - set->status = F_none; - set->flag = 0; - - // For writes, the id_data is the same as the id. - set->socket.id_data = set->socket.id; - - // Initialize the default file payload. - set->status = f_memory_array_increase_by(kt_tacocat_packet_headers_d, sizeof(f_string_map_t), (void **) &set->headers.array, &set->headers.used, &set->headers.size); - - if (F_status_is_error_not(set->status)) { - set->status = f_memory_array_increase_by(kt_tacocat_packet_prebuffer_d, sizeof(f_char_t), (void **) &set->buffer.string, &set->buffer.used, &set->buffer.size); - } - - if (F_status_is_error_not(set->status)) { - kt_tacocat_process_abstruse_initialize(main, set); - } + kt_tacocat_send_process_initialize(main, set); if (F_status_is_error(set->status)) { - macro_kt_send_process_handle_error_exit_1(main, f_memory_array_increase_by, kt_tacocat_send_s, set->network, set->status, set->name, set->step); + macro_kt_send_process_handle_error_exit_1(main, kt_tacocat_send_process_initialize, kt_tacocat_send_s, set->network, set->status, set->name, set->step); } set->step = kt_tacocat_socket_step_send_size_e; @@ -188,7 +171,7 @@ extern "C" { 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 **) &.array, &.used, &.size); + 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. @@ -205,7 +188,7 @@ extern "C" { kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(f_memory_array_increase_by), kt_tacocat_send_size_s, set->network, set->status, set->name); - return; + return F_done_not; } set->step = kt_tacocat_socket_step_send_build_e; @@ -216,7 +199,10 @@ extern "C" { state_local.data = &set->write_state; fl_fss_payload_header_map(set->abstruses, &set->headers, &state_local); - macro_kt_send_process_handle_error_exit_1(main, fl_fss_payload_header_map, kt_tacocat_send_build_s, set->network, state_local.status, set->name, set->step); + + set->status = state_local.status; + + macro_kt_send_process_handle_error_exit_1(main, fl_fss_payload_header_map, kt_tacocat_send_build_s, set->network, set->status, set->name, set->step); set->step = kt_tacocat_socket_step_send_header_e; } @@ -345,19 +331,30 @@ extern "C" { set->size_done += written; + set->status = F_okay; + set->step = kt_tacocat_socket_step_send_wait_e; + + // 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_header_e; + set->step = kt_tacocat_socket_step_send_wait_e; 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)) { @@ -381,6 +378,105 @@ extern "C" { } #endif // _di_kt_tacocat_send_process_ +#ifndef _di_kt_tacocat_send_process_initialize_ + void kt_tacocat_send_process_initialize(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) { + + if (!main || !set) return; + + set->abstruses.used = 0; + set->buffer.used = 0; + set->id.used = 0; + set->cache.used = 0; + set->header.used = 0; + set->headers.used = 0; + set->objects.used = 0; + set->contents.used = 0; + set->objects_delimits.used = 0; + set->contents_delimits.used = 0; + set->comments.used = 0; + set->retry = 0; + set->size_done = 0; + set->size_total = 0; + set->file.size_read = set->size_block; + set->socket.size_read = kt_tacocat_packet_read_d; + set->socket.id_data = -1; + set->range.start = 1; + set->range.stop = 0; + set->state.status = F_none; + set->status = F_none; + set->packet.control = 0; + set->packet.size = 0; + set->packet.payload.start = 1; + set->packet.payload.stop = 0; + set->part = 0; + set->parts.used = 0; + set->flag = 0; + + // For writes, the id_data is the same as the id. + set->socket.id_data = set->socket.id; + + // Initialize the default file payload. + set->status = f_memory_array_increase_by(kt_tacocat_packet_headers_d, sizeof(f_string_map_t), (void **) &set->headers.array, &set->headers.used, &set->headers.size); + + if (F_status_is_error_not(set->status)) { + set->status = f_memory_array_increase_by(kt_tacocat_packet_prebuffer_d, sizeof(f_char_t), (void **) &set->buffer.string, &set->buffer.used, &set->buffer.size); + } + + if (F_status_is_error_not(set->status)) { + set->status = f_memory_array_increase_by(kt_tacocat_packet_id_length_d, sizeof(f_char_t), (void **) &set->id.string, &set->id.used, &set->id.size); + } + + if (F_status_is_error_not(set->status)) { + f_char_t id[kt_tacocat_packet_id_length_d]; + f_string_static_t id_buffer = macro_f_string_static_t_initialize_2(id, 0); + uint8_t modded = 0; + + memset(id, 0, kt_tacocat_packet_id_length_d); + + if (F_status_is_error_not(f_random_read(0, kt_tacocat_packet_id_length_d, &id_buffer.string, &id_buffer.used))) { + for (uint8_t i = 0; i < id_buffer.used; i += macro_f_utf_byte_width(id[i])) { + + if (f_utf_is_alphabetic_digit(id + i, kt_tacocat_packet_id_length_d - i, 0) == F_true) { + set->id.string[set->id.used++] = id[i]; + + if (macro_f_utf_byte_width(id[i]) > 1) { + set->id.string[set->id.used++] = id[i + 1]; + + if (macro_f_utf_byte_width(id[i]) > 2) { + set->id.string[set->id.used++] = id[i + 2]; + + if (macro_f_utf_byte_width(id[i]) > 3) { + set->id.string[set->id.used++] = id[i + 3]; + } + } + } + } + else { + modded = ((uint8_t) id[i]) % 36; + + // Fallback to ASCII based on current index position. + if (modded < 10) { + set->id.string[set->id.used++] = (modded) + 48; + } + else if (modded < 36) { + set->id.string[set->id.used++] = (modded) + 55; // ASCII 65 - 10 = 55. + } + else { + set->id.string[set->id.used++] = (modded) + 61; // ASCII 97 - 36 = 61. + } + } + } // for + } + else { + // @todo manually generate something, probably use the file name and the port number. + } + } + + if (F_status_is_error_not(set->status)) { + kt_tacocat_process_abstruse_initialize(main, set); + } + } +#endif // _di_kt_tacocat_send_process_initialize_ #ifdef __cplusplus } // extern "C" #endif diff --git a/sources/c/tacocat/main/send.h b/sources/c/tacocat/main/send.h index 8cb68b4..556dea0 100644 --- a/sources/c/tacocat/main/send.h +++ b/sources/c/tacocat/main/send.h @@ -55,18 +55,49 @@ extern "C" { * F_payload_too_large (with error bit) on total payload size is too large. * F_too_large (with error bit) on file too large. * + * Errors (with error bit) from: kt_tacocat_process_abstruse_initialize() + * * @return - * F_done on success and done processing. - * F_done_not on success but not done processing. + * F_done on success and done processing. + * F_done_not on success but not done processing. * - * F_parameter (with error bit) on invalid parameter. + * F_parameter (with error bit) on invalid parameter. * * @see f_socket_read_stream() + * @see kt_tacocat_send_process_initialize() */ #ifndef _di_kt_tacocat_send_process_ extern f_status_t kt_tacocat_send_process(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set); #endif // _di_kt_tacocat_send_process_ +/** + * Process the network socket, performing the initialization step such as when step == 0. + * + * @param main + * The main program and settings data. + * + * 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_packet_too_large (with error bit) on total packet size is too large. + * F_payload_too_large (with error bit) on total payload size is too large. + * F_too_large (with error bit) on file too large. + * + * Errors (with error bit) from: f_memory_array_increase_by() + * Errors (with error bit) from: kt_tacocat_process_abstruse_initialize() + * + * @see f_memory_array_increase_by() + * @see kt_tacocat_process_abstruse_initialize() + */ +#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_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/sources/c/tacocat/main/tacocat.h b/sources/c/tacocat/main/tacocat.h index 9a44f2f..4faa2e6 100644 --- a/sources/c/tacocat/main/tacocat.h +++ b/sources/c/tacocat/main/tacocat.h @@ -66,6 +66,7 @@ #include #include #include +#include #include #include #include -- 1.8.3.1