From 297cca986416d0bc8db711d754149948fb66610c Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Wed, 27 Dec 2023 23:10:21 -0600 Subject: [PATCH] Progress: Further work in TacocaT. I have confirmed that the send and receive to/from tacocat works. This does send and receive with the current code but the written data writes the entire packet rather than just the payload. This behavior will change. This begins changing the design to make the receive consistent with some design differences from the send. The received packet needs to be processed using the appropriate FSS functions. Much of this is commented out next to where the work needs to be done. --- data/build/tacocat/dependencies | 1 + data/build/tacocat/settings | 2 +- sources/c/tacocat/main/common.c | 12 ++ sources/c/tacocat/main/common/define.h | 12 +- sources/c/tacocat/main/common/enumeration.h | 18 ++- sources/c/tacocat/main/common/type.c | 20 +++ sources/c/tacocat/main/common/type.h | 52 ++++++- sources/c/tacocat/main/receive.c | 217 ++++++++++++++++++++-------- sources/c/tacocat/main/receive.h | 29 ++-- sources/c/tacocat/main/send.c | 61 +++++--- sources/c/tacocat/main/send.h | 19 ++- sources/c/tacocat/main/tacocat.h | 2 + 12 files changed, 326 insertions(+), 119 deletions(-) diff --git a/data/build/tacocat/dependencies b/data/build/tacocat/dependencies index f3be563..9b4c10e 100644 --- a/data/build/tacocat/dependencies +++ b/data/build/tacocat/dependencies @@ -27,5 +27,6 @@ fl_fss fl_print fll_error +fll_fss fll_print fll_program diff --git a/data/build/tacocat/settings b/data/build/tacocat/settings index 42f3596..3366b94 100644 --- a/data/build/tacocat/settings +++ b/data/build/tacocat/settings @@ -32,7 +32,7 @@ build_indexer_arguments rcs build_language c build_libraries -lc -build_libraries-individual -lfll_error -lfll_print -lfll_program -lfl_conversion -lfl_fss -lfl_print -lf_color -lf_compare -lf_console -lf_conversion -lf_file -lf_fss -lf_memory -lf_network -lf_path -lf_pipe -lf_print -lf_signal -lf_socket -lf_status_string -lf_string -lf_time -lf_type_array -lf_utf +build_libraries-individual -lfll_error -lfll_fss -lfll_print -lfll_program -lfl_conversion -lfl_fss -lfl_print -lf_color -lf_compare -lf_console -lf_conversion -lf_file -lf_fss -lf_memory -lf_network -lf_path -lf_pipe -lf_print -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 diff --git a/sources/c/tacocat/main/common.c b/sources/c/tacocat/main/common.c index 7dbc150..522a32b 100644 --- a/sources/c/tacocat/main/common.c +++ b/sources/c/tacocat/main/common.c @@ -162,6 +162,10 @@ extern "C" { } main->setting.interval = number; + + if (number < kt_tacocat_interval_poll_fast_d) { + main->setting.interval_fast = number; + } } else if (main->program.parameters.array[kt_tacocat_parameter_interval_e].result & f_console_result_found_e) { main->setting.state.status = F_status_set_error(F_parameter); @@ -346,6 +350,14 @@ extern "C" { sets[i]->array[j].packet.payload.stop = 0; sets[i]->array[j].retry = 0; sets[i]->array[j].status = F_okay; + sets[i]->array[j].range.start = 1; + sets[i]->array[j].range.stop = 0; + sets[i]->array[j].objects.used = 0; + sets[i]->array[j].contents.used = 0; + sets[i]->array[j].objects_delimits.used = 0; + sets[i]->array[j].contents_delimits.used = 0; + sets[i]->array[j].comments.used = 0; + sets[i]->array[j].state = main->setting.state; sets[i]->array[j].socket.id = -1; sets[i]->array[j].socket.id_data = -1; sets[i]->array[j].socket.form = f_socket_address_form_generic_e; diff --git a/sources/c/tacocat/main/common/define.h b/sources/c/tacocat/main/common/define.h index 15c6da8..f8ca80e 100644 --- a/sources/c/tacocat/main/common/define.h +++ b/sources/c/tacocat/main/common/define.h @@ -33,7 +33,8 @@ extern "C" { * - peek: The size in bytes representing the size of the peek cache (should be set to at least "kt_tacocat_block_size_receive_d + 1" and must be greater than zero). * * kt_tacocat_interval_*_d: - * - poll: The time in milliseconds to poll for before returning (this is the amount of time poll() blocks). + * - poll: The time in milliseconds to poll for before returning (this is the amount of time poll() blocks). + * - poll_fast: The time in milliseconds to poll for before returning fo fast polls, such as when there is an active process (this is the amount of time poll() blocks). * * kt_tacocat_max_*_d: * - backlog: The max backlog in bytes size to use. @@ -67,7 +68,8 @@ extern "C" { #define kt_tacocat_cache_size_peek_d (kt_tacocat_block_size_receive_d + 1) - #define kt_tacocat_interval_poll_d 1400 // 1.4 second. + #define kt_tacocat_interval_poll_d 1400 // 1.4 second. + #define kt_tacocat_interval_poll_fast_d 50 // 0.05 second. #define kt_tacocat_max_backlog_d 0x400 #define kt_tacocat_max_buffer_d 0x10000000 // 0x10^0x5 * 0x100 (Which is 256 Megabytes (0x10^0x5 where the base unit is 16 rather than 10 or 2 (maybe call this xytes? Megaxytes?)). @@ -101,11 +103,11 @@ extern "C" { * The same as macro_setting_load_handle_send_receive_error_continue_1() but intended for file errors. * * macro_kt_receive_process_handle_error_exit_1: - * Intended to be used for handling an error during the receive process while not processing within flag kt_tacocat_socket_flag_receive_block_control_e. + * Intended to be used for handling an error during the receive process while not processing within flag kt_tacocat_socket_flag_receive_control_e. * The parameter id_data and is set to 0 to disable and is otherwise an address pointer. * * macro_kt_receive_process_begin_handle_error_exit_1: - * Intended to be used for handling an error during the receive process while processing within flag kt_tacocat_socket_flag_receive_block_control_e. + * Intended to be used for handling an error during the receive process while processing within flag kt_tacocat_socket_flag_receive_control_e. * * @todo document macro_kt_send_process_handle_error_exit_1. */ @@ -168,7 +170,7 @@ extern "C" { \ flag = 0; \ \ - return; \ + return F_done_not; \ } #define macro_kt_receive_process_begin_handle_error_exit_1(main, method, network, status, name, flag) \ diff --git a/sources/c/tacocat/main/common/enumeration.h b/sources/c/tacocat/main/common/enumeration.h index 747e715..ce24f5c 100644 --- a/sources/c/tacocat/main/common/enumeration.h +++ b/sources/c/tacocat/main/common/enumeration.h @@ -130,15 +130,21 @@ extern "C" { * Individual socket-specific flags for receiving. * * kt_tacocat_socket_flag_receive_*_e: - * - none: No flags set. - * - block_control: Reading and processing the Control block and Size block. - * - block_payload: Reading and processing the Payload block. + * - none: No flags set. + * - control: Reading and processing the Control block and Size block. + * - packet: Reading and processing the rest of the Packet block (the Header and Payload). + * - check: Process and check the loaded Payload block, processing the Header. + * - write: Save the loaded Payload block to the file (write to the file). + * - done: Done processing file. */ #ifndef _di_kt_tacocat_socket_flag_receive_e_ enum { - kt_tacocat_socket_flag_receive_none_e = 0x0, - kt_tacocat_socket_flag_receive_block_control_e = 0x1, - kt_tacocat_socket_flag_receive_block_payload_e = 0x2, + kt_tacocat_socket_flag_receive_none_e = 0x0, + kt_tacocat_socket_flag_receive_control_e = 0x1, + kt_tacocat_socket_flag_receive_packet_e = 0x2, + kt_tacocat_socket_flag_receive_check_e = 0x4, + kt_tacocat_socket_flag_receive_write_e = 0x8, + kt_tacocat_socket_flag_receive_done_e = 0x10, }; // enum #endif // _di_kt_tacocat_socket_flag_receive_e_ diff --git a/sources/c/tacocat/main/common/type.c b/sources/c/tacocat/main/common/type.c index a985eb7..8c5ba3d 100644 --- a/sources/c/tacocat/main/common/type.c +++ b/sources/c/tacocat/main/common/type.c @@ -50,6 +50,26 @@ extern "C" { f_file_close_id(&array[i].socket.id_data); f_socket_disconnect(&array[i].socket, f_socket_close_fast_e); + if (array[i].objects.size) { + f_memory_array_resize(0, sizeof(f_range_t), (void **) &array[i].objects.array, &array[i].objects.used, &array[i].objects.size); + } + + if (array[i].contents.size) { + f_memory_arrays_resize(0, sizeof(f_range_t), (void **) &array[i].contents.array, &array[i].contents.used, &array[i].contents.size, &f_rangess_delete_callback); + } + + if (array[i].objects_delimits.size) { + f_memory_array_resize(0, sizeof(f_number_unsigned_t), (void **) &array[i].objects_delimits.array, &array[i].objects_delimits.used, &array[i].objects_delimits.size); + } + + if (array[i].objects_delimits.size) { + f_memory_array_resize(0, sizeof(f_number_unsigned_t), (void **) &array[i].contents_delimits.array, &array[i].contents_delimits.used, &array[i].contents_delimits.size); + } + + if (array[i].comments.size) { + f_memory_array_resize(0, sizeof(f_range_t), (void **) &array[i].comments.array, &array[i].comments.used, &array[i].comments.size); + } + if (array[i].buffer.size) { f_memory_array_resize(0, sizeof(f_char_t), (void **) &array[i].buffer.string, &array[i].buffer.used, &array[i].buffer.size); } diff --git a/sources/c/tacocat/main/common/type.h b/sources/c/tacocat/main/common/type.h index 7513334..25ae0d1 100644 --- a/sources/c/tacocat/main/common/type.h +++ b/sources/c/tacocat/main/common/type.h @@ -29,6 +29,14 @@ extern "C" { * socket: Socket structure. * status: The status of the socket operations. * + * range: A generic range, often used for FSS processing. + * objects: An array of FSS Objects. + * contents: An array of FSS Contents. + * objects_delimits: An array of FSS Object delimits. + * contents_delimits: An array of FSS Content delimits. + * comments: An array of FSS comments. + * state: Basic state information, usually passed to the FSS functions. + * * buffer: A buffer for sending or receiving data between clients. * cache: A cache used for various purposes, but primarily for the building of the send packet. * client: A single client address for some network connection. @@ -53,6 +61,14 @@ extern "C" { f_socket_t socket; f_status_t status; + f_range_t range; + f_ranges_t objects; + f_rangess_t contents; + f_number_unsigneds_t objects_delimits; + f_number_unsigneds_t contents_delimits; + f_ranges_t comments; + f_state_t state; + f_string_dynamic_t buffer; f_string_dynamic_t cache; f_string_dynamic_t client; @@ -76,6 +92,13 @@ extern "C" { f_file_t_initialize, \ f_socket_t_initialize, \ f_status_t_initialize, \ + f_range_t_initialize, \ + f_ranges_t_initialize, \ + f_rangess_t_initialize, \ + f_number_unsigneds_t_initialize, \ + f_number_unsigneds_t_initialize, \ + f_ranges_t_initialize, \ + f_state_t_initialize, \ f_string_dynamic_t_initialize, \ f_string_dynamic_t_initialize, \ f_string_dynamic_t_initialize, \ @@ -99,6 +122,13 @@ extern "C" { f_poll_t_initialize, \ f_socket_t_initialize, \ f_status_t_initialize, \ + f_range_t_initialize, \ + f_ranges_t_initialize, \ + f_rangess_t_initialize, \ + f_number_unsigneds_t_initialize, \ + f_number_unsigneds_t_initialize, \ + f_ranges_t_initialize, \ + f_state_t_initialize, \ f_string_dynamic_t_initialize, \ f_string_dynamic_t_initialize, \ f_string_dynamic_t_initialize, \ @@ -122,6 +152,13 @@ extern "C" { f_poll_t_initialize, \ f_socket_t_initialize, \ f_status_t_initialize, \ + f_range_t_initialize, \ + f_ranges_t_initialize, \ + f_rangess_t_initialize, \ + f_number_unsigneds_t_initialize, \ + f_number_unsigneds_t_initialize, \ + f_ranges_t_initialize, \ + f_state_t_initialize, \ f_string_dynamic_t_initialize, \ f_string_dynamic_t_initialize, \ f_string_dynamic_t_initialize, \ @@ -164,9 +201,12 @@ extern "C" { * This is passed to the program-specific main entry point to designate program settings. * These program settings are often processed from the program arguments (often called the command line arguments). * - * flag: Flags passed to the main function. - * interval: The poll interval to use. - * max_buffer: The maximum buffer size to use on receive. + * flag: Flags passed to the main function. + * interval: The poll interval to use. + * interval_fast: A poll interval to use when needing the interval to be short. + * max_buffer: The maximum buffer size to use on receive. + * active_receive: The number of active receive processes, after initial connection is established. + * active_send: The number of active send processes, after initial connection is established. * * status_receive: A status used exclusively by the receive thread. * status_send: A status used exclusively by the send thread. @@ -184,7 +224,10 @@ extern "C" { typedef struct { uint64_t flag; uint64_t interval; + uint64_t interval_fast; f_number_unsigned_t max_buffer; + f_number_unsigned_t active_receive; + f_number_unsigned_t active_send; f_status_t status_receive; f_status_t status_send; @@ -203,7 +246,10 @@ extern "C" { { \ kt_tacocat_main_flag_max_buffer_e, \ kt_tacocat_interval_poll_d, \ + kt_tacocat_interval_poll_fast_d, \ kt_tacocat_max_buffer_d, \ + 0, \ + 0, \ F_okay, \ F_okay, \ F_okay, \ diff --git a/sources/c/tacocat/main/receive.c b/sources/c/tacocat/main/receive.c index e58f8c5..ace18ca 100644 --- a/sources/c/tacocat/main/receive.c +++ b/sources/c/tacocat/main/receive.c @@ -16,9 +16,9 @@ extern "C" { kt_tacocat_process_socket_set_receive(main); - if (F_status_is_error_not(main->setting.status_receive)) { + if (F_status_is_error_not(main->setting.status_receive) && main->setting.receive.used) { do { - main->setting.status_receive = f_file_poll(main->setting.receive_polls, main->setting.interval); + main->setting.status_receive = f_file_poll(main->setting.receive_polls, main->setting.active_receive ? main->setting.interval_fast : main->setting.interval); if (main->program.signal_received) { main->setting.status_receive = F_status_set_error(F_interrupt); @@ -26,18 +26,54 @@ extern "C" { return 0; } - // Skip if status is an error or is F_time_out. + // @todo or check if there is any lingering in-progress process not waiting on receive. + // @todo when there is a lingering iin-progress process, change the poll timeout to a shorter period to process the lingering process more. + // Skip if status from poll is an error or is F_time_out. if (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; if (main->setting.receive_polls.array[i].revents & (f_poll_read_e)) { - kt_tacocat_receive_process(main, &main->setting.receive.array[i]); + if (kt_tacocat_receive_process(main, &main->setting.receive.array[i]) == F_done) { + if (F_status_is_error(main->setting.receive.array[i].status)) { + // @todo there probably should be a timeout as well as a retry, which should be checked if the poll read condition above is false. + if (++main->setting.receive.array[i].retry >= kt_tacocat_startup_retry_max_d) { + f_file_close(&main->setting.receive.array[i].file); + + // Keep error bit but set state to done to designate that nothing else is to be done. + main->setting.receive.array[i].status = F_status_set_error(F_done); + + if (main->setting.receive.array[i].flag) { + main->setting.receive.array[i].flag = 0; + --main->setting.active_receive; + } + + kt_tacocat_print_error_on_max_retries(&main->program.error, kt_tacocat_receive_s, main->setting.receive.array[i].network, main->setting.receive.array[i].name); + } + + // @todo if flag is kt_tacocat_socket_flag_receive_control_e, check if error is either F_packet_too_small or F_packet_too_large. This is a non-retrying error. + } + } + else { + if (F_status_is_error(main->setting.receive.array[i].status)) { + if (++main->setting.receive.array[i].retry >= kt_tacocat_startup_retry_max_d) { + f_file_close(&main->setting.receive.array[i].file); + + // Keep error bit but set state to done to designate that nothing else is to be done. @todo review and confirm if this assignment with error bit set is needed anymore or should be changed. + main->setting.receive.array[i].status = F_status_set_error(F_done); + + if (main->setting.receive.array[i].flag) { + main->setting.receive.array[i].flag = 0; + --main->setting.active_receive; + } + + kt_tacocat_print_error_on_max_retries(&main->program.error, kt_tacocat_receive_s, main->setting.receive.array[i].network, main->setting.receive.array[i].name); + } + } + } main->setting.receive_polls.array[i].revents = 0; - - if (F_status_is_error(main->setting.state.status)) continue; } } // for } @@ -58,42 +94,62 @@ extern "C" { #endif // _di_kt_tacocat_receive_ #ifndef _di_kt_tacocat_receive_process_ - void kt_tacocat_receive_process(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) { + f_status_t kt_tacocat_receive_process(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) { - if (!main || !set) return; + if (!main || !set) return F_status_set_error(F_parameter); // This is a new packet (kt_tacocat_socket_flag_receive_none_e). if (!(set->flag)) { kt_tacocat_print_message_receive_operation_received(&main->program.message, *set); - set->flag = kt_tacocat_socket_flag_receive_block_control_e; - set->retry = 0; + 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->flag = kt_tacocat_socket_flag_receive_control_e; - set->status = f_file_open(set->name, F_file_mode_all_rw_d, &set->file); + ++main->setting.active_receive; + } - if (F_status_is_error(set->status)) { - kt_tacocat_print_error_on_file_receive(&main->program.error, macro_kt_tacocat_f(f_file_open), kt_tacocat_receive_s, set->network, set->status, set->name, f_file_operation_open_s); + if (set->retry >= kt_tacocat_startup_retry_max_d) { + f_file_close(&set->file); - return; - } + // 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); + set->flag = 0; + --main->setting.active_receive; + + kt_tacocat_print_error_on_max_retries(&main->program.error, kt_tacocat_receive_s, set->network, set->name); + + return F_done; } // Load the header of the new packet. - if (set->flag & kt_tacocat_socket_flag_receive_block_control_e) { + if (set->flag & kt_tacocat_socket_flag_receive_control_e) { kt_tacocat_receive_process_control(main, set); - if (set->buffer.used < kt_tacocat_packet_peek_d) { - f_file_close_id(&set->socket.id_data); + if (set->buffer.used < kt_tacocat_packet_peek_d || F_status_is_error(set->status)) { + --main->setting.active_receive; - return; - } - - if (set->buffer.used < kt_tacocat_packet_peek_d) { - f_file_close_id(&set->socket.id_data); - - return; + return F_done; } // Reset the buffer to allow for reusing and writing to the file in blocks. @@ -103,51 +159,101 @@ 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); + + set->retry = 0; + set->flag = kt_tacocat_socket_flag_receive_packet_e; } - if (set->flag & kt_tacocat_socket_flag_receive_block_payload_e) { + if (set->flag & kt_tacocat_socket_flag_receive_packet_e) { size_t length_read = 0; set->status = f_socket_read_stream(&set->socket, 0, (void *) set->buffer.string, &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); if (length_read) { - set->buffer.used = length_read; + set->retry = 0; + set->buffer.used += length_read; + set->flag = kt_tacocat_socket_flag_receive_check_e; + } + else { + ++set->retry; + } + } - set->status = f_file_write(set->file, set->buffer, 0); + if (set->flag & kt_tacocat_socket_flag_receive_check_e) { + // @todo after payload, a headers, and a save step. The check step will be the FSS processing check and if the proper step is reached, then set another flag to designate that the payload start has been found, process the headers (another flag), + set->range.start = 0; + set->range.stop = set->buffer.used - 1; + set->state.status = F_none; - // Keep going on error, but in the future more advanced error handling/recovery is needed to make this more robust. - if (F_status_is_error(set->status)) { - kt_tacocat_print_error_on_file_receive(&main->program.error, macro_kt_tacocat_f(f_file_write), kt_tacocat_receive_s, set->network, set->status, set->name, f_file_operation_write_s); - } + fll_fss_payload_read(set->buffer, &set->range, &set->objects, &set->contents, &set->objects_delimits, &set->contents_delimits, &set->comments, &set->state); - // Reset buffer used and increment counter. - set->packet.payload.stop += set->buffer.used; - set->buffer.used = 0; + // @todo before writing the buffer to the file, attempt to read the header, keep appending to the current buffer until in memory matches "payload:". + // @todo if the entire header is not available, then set flag back to kt_tacocat_socket_flag_receive_packet_e. + //extern void fll_fss_payload_read(const f_string_static_t buffer, f_range_t * const range, f_ranges_t * const objects, f_rangess_t * const contents, f_number_unsigneds_t * const objects_delimits, f_number_unsigneds_t * const contents_delimits, f_ranges_t * const comments, f_state_t * const state); + + /*if (set->packet.payload.stop + 1 < set->packet.size) { + set->flag = kt_tacocat_socket_flag_receive_packet_e; + + return F_data_not; + }*/ - f_file_close_id(&set->socket.id_data); + set->flag = kt_tacocat_socket_flag_receive_write_e; + } + + if (set->flag & kt_tacocat_socket_flag_receive_write_e) { + set->status = f_file_open(set->name, F_file_mode_all_rw_d, &set->file); - if (set->packet.payload.stop + 1 < set->packet.size) return; + if (F_status_is_error(set->status)) { + kt_tacocat_print_error_on_file_receive(&main->program.error, macro_kt_tacocat_f(f_file_open), kt_tacocat_receive_s, set->network, set->status, set->name, f_file_operation_open_s); + + return F_done_not; // @todo consider sending a file error to caller. This should not infinitely attempt to open on failure. } + + // @todo write only the Payload. + set->status = f_file_write(set->file, set->buffer, 0); + + // Keep going on error, but in the future more advanced error handling/recovery is needed to make this more robust. + if (F_status_is_error(set->status)) { + f_file_close(&set->file); + + kt_tacocat_print_error_on_file_receive(&main->program.error, macro_kt_tacocat_f(f_file_write), kt_tacocat_receive_s, set->network, set->status, set->name, f_file_operation_write_s); + } + + // Reset buffer used and increment counter. + set->packet.payload.stop += set->buffer.used; + set->buffer.used = 0; + + f_file_close(&set->file); + + set->flag = kt_tacocat_socket_flag_receive_done_e; } // Done processing the Packet. - kt_tacocat_print_message_receive_operation_complete(&main->program.message, *set); + if (set->flag & kt_tacocat_socket_flag_receive_done_e) { + kt_tacocat_print_message_receive_operation_complete(&main->program.message, *set); - f_file_close_id(&set->socket.id_data); - f_file_close(&set->file); - set->flag = 0; + f_file_close(&set->file); - if (set->buffer.size > kt_tacocat_max_maintain_d) { - set->buffer.used = 0; + set->flag = 0; + set->status = F_okay; + --main->setting.active_receive; - set->status = f_memory_array_resize(kt_tacocat_max_maintain_d, sizeof(f_char_t), (void **) &set->buffer.string, &set->buffer.used, &set->buffer.size); + if (set->buffer.size > kt_tacocat_max_maintain_d) { + set->buffer.used = 0; - // Report the resize error but do not fail. - if (F_status_is_error(set->status)) { - kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(f_memory_array_resize), kt_tacocat_receive_s, set->network, set->status, set->name); + set->status = f_memory_array_resize(kt_tacocat_max_maintain_d, sizeof(f_char_t), (void **) &set->buffer.string, &set->buffer.used, &set->buffer.size); + + // Report the resize error but do not fail. + if (F_status_is_error(set->status)) { + kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(f_memory_array_resize), kt_tacocat_receive_s, set->network, set->status, set->name); + } } + + return F_done; } + + return F_done_not; } #endif // _di_kt_tacocat_receive_process_ @@ -177,7 +283,7 @@ extern "C" { set->buffer.used += length_read; - // Continue if the packet header is not fully ready. + // Try peeking again if the packet header is not fully ready. if (set->buffer.used < kt_tacocat_packet_peek_d) { // Peek ahead to see if the client has closed the connection (all the intended data should have been transmitted). @@ -195,11 +301,6 @@ extern "C" { if (!length_read) { kt_tacocat_print_error_on_packet_too_small(&main->program.error, kt_tacocat_receive_s, set->network, kt_tacocat_packet_peek_d, set->buffer.used); - set->buffer.used = 0; - set->flag = 0; - set->packet.control = 0; - set->packet.size = 0; - set->retry = 0; set->status = F_status_set_error(F_packet_too_small); return; @@ -210,11 +311,7 @@ extern "C" { // Connection is closed when length is 0. kt_tacocat_print_warning_on_client_closed(&main->program.warning, kt_tacocat_receive_s, set->network); - set->buffer.used = 0; set->flag = 0; - set->packet.control = 0; - set->packet.size = 0; - set->retry = 0; set->status = F_status_set_error(F_packet_too_small); return; @@ -241,9 +338,6 @@ extern "C" { } set->flag = 0; - set->packet.control = 0; - set->packet.size = 0; - set->retry = 0; if (set->status == F_packet_too_small || set->packet.size < kt_tacocat_packet_minimum_d) { set->status = F_status_set_error(F_packet_too_small); @@ -257,8 +351,7 @@ extern "C" { return; } - set->flag |= kt_tacocat_socket_flag_receive_block_payload_e; - set->flag -= kt_tacocat_socket_flag_receive_block_control_e; + set->flag = kt_tacocat_socket_flag_receive_packet_e; // The payload range "stop" is used to represent the total amount of bytes processed so far (uncluding the header). set->packet.payload.start = 0; diff --git a/sources/c/tacocat/main/receive.h b/sources/c/tacocat/main/receive.h index 8fd9aa6..a04d60f 100644 --- a/sources/c/tacocat/main/receive.h +++ b/sources/c/tacocat/main/receive.h @@ -20,9 +20,12 @@ extern "C" { * * Must be of type kt_tacocat_main_t. * - * This alters main.setting.state.status: + * This does not alter main.setting.state.status, except on interrupt signal. + * + * This alters main.setting.status_receive: * F_okay on success. - * F_child on child process exiting. + * + * F_interrupt (with error bit set) on interrupt received. * * @return * 0, always. @@ -37,19 +40,21 @@ extern "C" { * @param main * The main program and settings data. * - * This alters main.setting.state.status: + * 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. - * @param set - * The socket set to process. - * Must not be NULL. * * @see f_socket_read_stream() */ #ifndef _di_kt_tacocat_receive_process_ - extern void kt_tacocat_receive_process(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set); + extern f_status_t kt_tacocat_receive_process(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set); #endif // _di_kt_tacocat_receive_process_ /** @@ -58,14 +63,16 @@ extern "C" { * @param main * The main program and settings data. * - * This alters main.setting.state.status: + * 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. - * @param set - * The socket set to process. - * Must not be NULL. * * @see f_socket_read_stream() */ diff --git a/sources/c/tacocat/main/send.c b/sources/c/tacocat/main/send.c index fac69bf..6e7643b 100644 --- a/sources/c/tacocat/main/send.c +++ b/sources/c/tacocat/main/send.c @@ -17,6 +17,7 @@ extern "C" { kt_tacocat_process_socket_set_send(main); + // @todo this needs to integrate send_polls, for checking responses to sent packets. if (F_status_is_error_not(main->setting.status_send) && main->setting.send.used) { do { ready = F_okay; @@ -35,7 +36,6 @@ extern "C" { } } else { - // @todo the kt_tacocat_receive_process() and kt_tacocat_send_process() have different return designs, figure out which design to use and be consistent. // @todo in all cases error or success, when done be sure set->file is closed. // @todo on error during partial transfer either attempt to resend, attempt to send failure packet, or abandon. if (kt_tacocat_send_process(main, &main->setting.send.array[i]) == F_done) { @@ -79,11 +79,27 @@ extern "C" { if (!set->flag) { 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; + + // 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); @@ -137,14 +153,6 @@ extern "C" { set->abstruses.used = 7; - 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, macro_kt_tacocat_f(f_file_open), kt_tacocat_send_s, set->network, set->status, set->name, f_file_operation_open_s); - - return F_done_not; - } - set->flag = kt_tacocat_socket_flag_send_size_e; } @@ -152,17 +160,27 @@ extern "C" { f_file_close(&set->file); f_socket_disconnect(&set->socket, f_socket_close_fast_e); + set->flag = 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); - set->socket.id = -1; - set->socket.id_data = -1; kt_tacocat_print_error_on_max_retries(&main->program.error, kt_tacocat_send_s, set->network, set->name); return F_done; } - if (set->flag == kt_tacocat_socket_flag_send_size_e) { + if (set->flag & kt_tacocat_socket_flag_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, macro_kt_tacocat_f(f_file_open), 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; @@ -208,7 +226,7 @@ extern "C" { set->flag = kt_tacocat_socket_flag_send_build_e; } - if (set->flag == kt_tacocat_socket_flag_send_build_e) { + if (set->flag & kt_tacocat_socket_flag_send_build_e) { f_state_t state_local = main->setting.state; state_local.data = &set->write_state; @@ -218,7 +236,7 @@ extern "C" { set->flag = kt_tacocat_socket_flag_send_header_e; } - if (set->flag == kt_tacocat_socket_flag_send_header_e) { + if (set->flag & kt_tacocat_socket_flag_send_header_e) { // @todo this needs to check the current status, accodingly (for when multiple blocks are being sent). // Reserve the FSS Packet header, which will be calculated just before sending. @@ -270,7 +288,7 @@ extern "C" { set->flag = kt_tacocat_socket_flag_send_file_e; } - if (set->flag == kt_tacocat_socket_flag_send_file_e) { + if (set->flag & kt_tacocat_socket_flag_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); @@ -295,10 +313,11 @@ extern "C" { set->status = f_string_dynamic_terminate_after(&set->buffer); macro_kt_send_process_handle_error_exit_1(main, f_string_dynamic_terminate_after, kt_tacocat_send_combine_s, set->network, set->status, set->name, set->flag); + set->retry = 0; set->flag = kt_tacocat_socket_flag_send_check_e; } - if (set->flag == kt_tacocat_socket_flag_send_check_e) { + if (set->flag & kt_tacocat_socket_flag_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) { //} @@ -306,7 +325,7 @@ extern "C" { set->flag = kt_tacocat_socket_flag_send_encode_e; } - if (set->flag == kt_tacocat_socket_flag_send_encode_e) { + if (set->flag & kt_tacocat_socket_flag_send_encode_e) { const f_number_unsigned_t original = set->buffer.used; set->buffer.used = 0; @@ -322,7 +341,7 @@ extern "C" { set->flag = kt_tacocat_socket_flag_send_packet_e; } - if (set->flag == kt_tacocat_socket_flag_send_packet_e) { + if (set->flag & kt_tacocat_socket_flag_send_packet_e) { size_t written = 0; { @@ -353,7 +372,7 @@ extern "C" { } } - if (set->flag == kt_tacocat_socket_flag_send_done_e) { + if (set->flag & kt_tacocat_socket_flag_send_done_e) { set->status = f_file_close(&set->file); if (F_status_is_error(set->status)) { @@ -366,11 +385,7 @@ extern "C" { kt_tacocat_print_warning_on_file(&main->program.warning, macro_kt_tacocat_f(f_socket_disconnect), kt_tacocat_send_done_s, set->network, set->status, set->name, f_file_operation_close_s); } - f_file_close_id(&set->socket.id_data); - set->flag = 0; - set->size_done = 0; - set->socket.id = -1; set->socket.id_data = -1; set->status = F_okay; diff --git a/sources/c/tacocat/main/send.h b/sources/c/tacocat/main/send.h index 42d5a2f..d213b66 100644 --- a/sources/c/tacocat/main/send.h +++ b/sources/c/tacocat/main/send.h @@ -20,9 +20,12 @@ extern "C" { * * Must be of type kt_tacocat_main_t. * - * This alters main.setting.state.status: + * This does not alter main.setting.state.status, except on interrupt signal. + * + * This alters main.setting.status_send: * F_okay on success. - * F_child on child process exiting. + * + * F_interrupt (with error bit set) on interrupt received. * * @return * 0, always. @@ -40,17 +43,17 @@ extern "C" { * @param main * The main program and settings data. * - * This alters main.setting.state.status: + * 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. - * @param set - * The socket set to process. - * Must not be NULL. - * - * @todo Processing and logic around the return status needs to reviewed and updated. * * @see f_socket_read_stream() */ diff --git a/sources/c/tacocat/main/tacocat.h b/sources/c/tacocat/main/tacocat.h index 6b83270..7cf37c4 100644 --- a/sources/c/tacocat/main/tacocat.h +++ b/sources/c/tacocat/main/tacocat.h @@ -47,6 +47,8 @@ // FLL-2 includes. #include +#include +#include #include #include -- 1.8.3.1