This adds a lot more files but cleans up the code quite a bit.
The `kt_tacocat_receive_process()` function is now easier to read and follow.
Update the send steps.
build_sources_program program/kevux/tools/tacocat/main/common.c program/kevux/tools/tacocat/main/common/define.c program/kevux/tools/tacocat/main/common/enumeration.c program/kevux/tools/tacocat/main/common/string.c program/kevux/tools/tacocat/main/common/type.c
build_sources_program program/kevux/tools/tacocat/main/print/error.c program/kevux/tools/tacocat/main/print/message.c program/kevux/tools/tacocat/main/print/verbose.c program/kevux/tools/tacocat/main/print/warning.c
build_sources_program program/kevux/tools/tacocat/main/packet.c program/kevux/tools/tacocat/main/process.c program/kevux/tools/tacocat/main/receive.c program/kevux/tools/tacocat/main/send.c program/kevux/tools/tacocat/main/signal.c program/kevux/tools/tacocat/main/tacocat.c program/kevux/tools/tacocat/main/thread.c
+build_sources_program program/kevux/tools/tacocat/main/send/step/check.c program/kevux/tools/tacocat/main/send/step/control.c program/kevux/tools/tacocat/main/send/step/done.c program/kevux/tools/tacocat/main/send/step/extract.c program/kevux/tools/tacocat/main/send/step/find.c program/kevux/tools/tacocat/main/send/step/next.c program/kevux/tools/tacocat/main/send/step/packet.c program/kevux/tools/tacocat/main/send/step/write.c
build_sources_program program/kevux/tools/tacocat/main/send/step/build.c program/kevux/tools/tacocat/main/send/step/check.c program/kevux/tools/tacocat/main/send/step/done.c program/kevux/tools/tacocat/main/send/step/encode.c program/kevux/tools/tacocat/main/send/step/file.c program/kevux/tools/tacocat/main/send/step/header.c program/kevux/tools/tacocat/main/send/step/packet.c program/kevux/tools/tacocat/main/send/step/size.c program/kevux/tools/tacocat/main/send/step/wait.c
build_sources_program program/kevux/tools/tacocat/tacocat/config.c program/kevux/tools/tacocat/tacocat/tacocat.c program/kevux/tools/tacocat/tacocat/main.c program/kevux/tools/tacocat/tacocat/string.c
build_sources_library common.c common/define.c common/enumeration.c common/string.c common/type.c
build_sources_library print/error.c print/message.c print/verbose.c print/warning.c
build_sources_library packet.c process.c receive.c send.c signal.c tacocat.c thread.c
+build_sources_library receive/step/check.c receive/step/control.c receive/step/done.c receive/step/extract.c receive/step/find.c receive/step/next.c receive/step/packet.c receive/step/write.c
build_sources_library send/step/build.c send/step/check.c send/step/done.c send/step/encode.c send/step/file.c send/step/header.c send/step/packet.c send/step/size.c send/step/wait.c
build_sources_headers common.h common/define.h common/enumeration.h common/string.h common/type.h
build_sources_headers print/error.h print/message.h print/verbose.h print/warning.h
build_sources_headers packet.h process.h receive.h send.h signal.h tacocat.h thread.h
+build_sources_headers receive/step/check.h receive/step/control.h receive/step/done.h receive/step/extract.h receive/step/find.h receive/step/next.h receive/step/packet.h receive/step/write.h
build_sources_headers send/step/build.h send/step/check.h send/step/done.h send/step/encode.h send/step/file.h send/step/header.h send/step/packet.h send/step/size.h send/step/wait.h
build_sources_documentation man
*
* macro_kt_tacocat_handle_load_send_receive_error_file_continue_1:
* The same as macro_kt_tacocat_handle_load_send_receive_error_continue_1() but is for file errors.
- *
- * macro_kt_tacocat_handle_receive_process_begin_error_exit_1:
- * The same as macro_kt_tacocat_handle_receive_process_error_exit_1() but is for file errors.
- *
- * macro_kt_tacocat_handle_receive_process_error_exit_1:
- * For use in kt_tacocat_setting_load_send_receive() for 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_tacocat_handle_receive_process_invalid_packet_exit_1:
- * Similar to macro_kt_tacocat_handle_receive_process_error_exit_1() but calls kt_tacocat_print_error_on_packet_invalid().
*/
#ifndef _di_kt_tacocat_macros_d_
#define macro_kt_tacocat_handle_load_send_receive_error_continue_1() \
continue; \
}
- #define macro_kt_tacocat_handle_receive_process_error_exit_1(main, network, status, name, step, id_data) \
- if (F_status_is_error(status)) { \
- kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, kt_tacocat_receive_s, network, status, name); \
- \
- if (id_data) { \
- f_file_close_id(&(id_data)); \
- } \
- \
- step = 0; \
- \
- return F_done_not; \
- }
-
- #define macro_kt_tacocat_handle_receive_process_invalid_packet_exit_1(main, network, name, step, id_data) \
- kt_tacocat_print_error_on_packet_invalid(&main->program.error, kt_tacocat_receive_s, network, name); \
- \
- if (id_data) { \
- f_file_close_id(&(id_data)); \
- } \
- \
- step = 0; \
- \
- return F_done_not;
-
#define macro_kt_tacocat_handle_receive_process_begin_error_exit_1(main, network, status, name, step) \
if (F_status_is_error(status)) { \
kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, kt_tacocat_receive_s, network, status, name); \
if (F_status_is_error(set->status)) {
kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, direction, set->network, set->status, set->name);
- if (set->socket.id_data) {
+ if (set->socket.id_data != -1) {
f_file_close_id(&set->socket.id_data);
}
// Load the header of the new packet.
if (set->step == kt_tacocat_socket_step_receive_control_e) {
- kt_tacocat_receive_process_control(main, set);
-
- if (set->buffer.used < kt_tacocat_packet_peek_d || F_status_is_error(set->status)) {
- if (main->setting.active_receive) {
- --main->setting.active_receive;
- }
-
- return F_done;
+ if (kt_tacocat_receive_step_control(main, set) == F_complete) {
+ return F_status_is_error(set->status) ? F_status_set_error(F_done) : F_done;
}
-
- // Reset the buffer to allow for reusing and writing to the file in blocks.
- set->buffer.used = 0;
-
- // 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_tacocat_handle_receive_process_error_exit_1(main, set->network, set->status, set->name, set->step, set->socket.id_data);
-
- set->retry = 0;
- set->buffer.used = 0;
- set->step = kt_tacocat_socket_step_receive_packet_e;
}
if (set->step == kt_tacocat_socket_step_receive_packet_e) {
- 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_tacocat_handle_receive_process_error_exit_1(main, set->network, set->status, set->name, set->step, set->socket.id_data);
-
- if (length_read) {
- set->retry = 0;
- set->buffer.used += length_read;
-
- // This is not a valid packet if the actual size is greater than expected.
- if (set->buffer.used > set->packet.size) {
- kt_tacocat_print_error_on_packet_too_large(&main->program.error, kt_tacocat_receive_s, set->network, set->packet.size, set->buffer.used);
-
- set->status = F_status_set_error(F_packet_too_large);
-
- return F_done;
- }
-
- // Initialize the range to start reading after the Control and Size blocks.
- if (set->range.start > set->range.stop) {
- set->range.start = F_fss_simple_packet_block_header_size_d;
- }
-
- set->range.stop = set->buffer.used - 1;
- set->step = kt_tacocat_socket_step_receive_find_e;
- }
- else {
- ++set->retry;
+ if (kt_tacocat_receive_step_packet(main, set) == F_complete) {
+ return F_status_is_error(set->status) ? F_status_set_error(F_done) : F_done;
}
}
if (set->step == kt_tacocat_socket_step_receive_find_e) {
- set->state.status = F_none;
-
- fll_fss_payload_read(set->buffer, &set->range, &set->objects, &set->contents, &set->objects_delimits, &set->contents_delimits, &set->comments, &set->state);
-
- // Note that F_fss_found_object_content_not is not treated as an error because the "payload" section is optional.
- if (F_status_is_error(set->state.status) && F_status_set_fine(set->state.status) != F_fss_found_object_content_not) {
- switch (F_status_set_fine(set->state.status)) {
- case F_okay:
- case F_okay_eos:
- case F_okay_stop:
-
- if (set->buffer.used == set->packet.size) {
-
- // The packet is fully loaded and there is no "payload" section.
- set->step = kt_tacocat_socket_step_receive_extract_e;
- }
- else {
-
- // Seek the left-most new line from the current position to ensure that the next pass potentially reads a complete line.
- while (set->range.start && set->buffer.string[set->range.start] != f_string_eol_s.string[0]) {
- --set->range.start;
- } // while
-
- // No packet is found and is not yet finished loading the data.
- set->step = kt_tacocat_socket_step_receive_packet_e;
- }
-
- break;
-
- default:
-
- // Seek the left-most new line from the current position to ensure that the next pass potentially reads a complete line.
- while (set->range.start && set->buffer.string[set->range.start] != f_string_eol_s.string[0]) {
- --set->range.start;
- } // while
-
- if (set->buffer.used != set->packet.size) {
- set->step = kt_tacocat_socket_step_receive_packet_e;
- }
-
- ++set->retry;
-
- break;
- }
- }
- else {
- switch (F_status_set_fine(set->state.status)) {
- case F_okay:
- case F_okay_eos:
- case F_okay_stop:
- case F_data_not:
- case F_data_not_eos:
- case F_data_not_stop:
- case F_fss_found_object_content_not:
- set->step = kt_tacocat_socket_step_receive_extract_e;
-
- break;
-
- default:
- ++set->retry;
-
- break;
- }
- }
+ kt_tacocat_receive_step_find(main, set);
}
if (set->step == kt_tacocat_socket_step_receive_extract_e) {
- 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_check_e;
+ kt_tacocat_receive_step_extract(main, set);
}
if (set->step == kt_tacocat_socket_step_receive_check_e) {
- if (set->parts.used) {
- if (set->abstruses.array[1].value.type != f_abstruse_unsigned_e) {
- macro_kt_tacocat_handle_receive_process_invalid_packet_exit_1(main, set->network, set->name, set->step, set->socket.id_data);
- }
-
- // @todo determine type of packet and process.
- }
- else {
-
- // The packet should only be a 'file' type for the first packet.
- if (set->abstruses.array[1].value.type != f_abstruse_unsigned_e || set->abstruses.array[1].value.is.a_unsigned != kt_tacocat_packet_type_file_d) {
- macro_kt_tacocat_handle_receive_process_invalid_packet_exit_1(main, set->network, set->name, set->step, set->socket.id_data);
- }
-
- 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_tacocat_handle_receive_process_error_exit_1(main, set->network, set->status, set->name, set->step, 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 {
- macro_kt_tacocat_handle_receive_process_invalid_packet_exit_1(main, set->network, set->name, set->step, set->socket.id_data);
- }
-
- if (set->abstruses.array[3].value.type == f_abstruse_unsigned_e) {
- set->part = set->abstruses.array[3].value.is.a_unsigned;
- }
- else {
- macro_kt_tacocat_handle_receive_process_invalid_packet_exit_1(main, set->network, set->name, set->step, set->socket.id_data);
- }
- }
-
- set->step = kt_tacocat_socket_step_receive_write_e;
+ kt_tacocat_receive_step_check(main, set);
}
if (set->step == kt_tacocat_socket_step_receive_write_e) {
- set->status = f_file_open(set->name, F_file_mode_all_rw_d, &set->file);
-
- if (F_status_is_error(set->status)) {
- kt_tacocat_print_error_on_file_receive(&main->program.error, F_status_debug_source_d, kt_tacocat_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.
- }
-
- set->status = f_file_write_range(set->file, set->buffer, set->packet.payload, 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, F_status_debug_source_d, kt_tacocat_receive_s, set->network, set->status, set->name, f_file_operation_write_s);
- }
-
- f_file_close(&set->file);
-
- set->buffer.used = 0;
- set->step = kt_tacocat_socket_step_receive_next_e;
+ kt_tacocat_receive_step_write(main, set);
}
if (set->step == kt_tacocat_socket_step_receive_next_e) {
- // @todo
-
- set->step = kt_tacocat_socket_step_receive_done_e;
+ kt_tacocat_receive_step_next(main, set);
}
// Done processing the Packet.
if (set->step == kt_tacocat_socket_step_receive_done_e) {
- kt_tacocat_print_message_receive_operation_complete(&main->program.message, *set);
-
- f_file_close(&set->file);
-
- set->step = 0;
- set->status = F_okay;
-
- if (main->setting.active_receive) {
- --main->setting.active_receive;
- }
-
- if (set->buffer.size > kt_tacocat_max_maintain_d) {
- set->buffer.used = 0;
-
- 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, F_status_debug_source_d, kt_tacocat_receive_s, set->network, set->status, set->name);
- }
- }
+ kt_tacocat_receive_step_done(main, set);
return F_done;
}
- return F_done_not;
+ return F_status_is_error(set->status) ? F_status_set_error(F_data_not) : F_data_not;
}
#endif // _di_kt_tacocat_receive_process_
* F_done_not on success but not done processing.
*
* F_parameter (with error bit) on invalid parameter.
+ * F_done (with error bit) on error but done processing.
+ * F_done_not (with error bit) on error and not done processing.
*
* @see f_file_open()
* @see f_file_write()
--- /dev/null
+#include "../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_tacocat_receive_step_check_
+ void kt_tacocat_receive_step_check(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+ if (!main || !set || F_status_is_error(set->status)) return;
+
+ uint8_t failure = F_false;
+
+ if (set->parts.used) {
+ if (set->abstruses.array[1].value.type != f_abstruse_unsigned_e) {
+ failure = F_true;
+
+ set->status = F_status_set_error(F_type_not);
+ }
+ else {
+ // @todo determine type of packet and process.
+ }
+ }
+ else {
+
+ // The packet should only be a 'file' type for the first packet.
+ if (set->abstruses.array[1].value.type != f_abstruse_unsigned_e || set->abstruses.array[1].value.is.a_unsigned != kt_tacocat_packet_type_file_d) {
+ failure = F_true;
+
+ set->status = F_status_set_error(F_first_not);
+ }
+
+ if (!failure) {
+ 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);
+
+ if (F_status_is_error(set->status)) {
+ kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, kt_tacocat_receive_s, set->network, set->status, set->name);
+
+ failure = F_true;
+ }
+ else {
+ memset(set->parts.array, 0, sizeof(f_number_unsigned_t));
+
+ set->parts.used = set->abstruses.array[4].value.is.a_unsigned;
+ }
+ }
+ else {
+ failure = F_true;
+
+ set->status = F_status_set_error(F_type_not);
+ }
+
+ if (!failure) {
+ if (set->abstruses.array[3].value.type == f_abstruse_unsigned_e) {
+ set->part = set->abstruses.array[3].value.is.a_unsigned;
+ }
+ else {
+ failure = F_true;
+
+ set->status = F_status_set_error(F_type_not);
+ }
+ }
+ }
+ }
+
+ if (failure) {
+ if (set->socket.id_data != -1) {
+ f_file_close_id(&set->socket.id_data);
+ }
+
+ set->step = 0;
+
+ return;
+ }
+
+ set->step = kt_tacocat_socket_step_receive_write_e;
+ set->status = F_okay;
+ }
+#endif // _di_kt_tacocat_receive_step_check_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides receive step check functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_receive_step_check_h
+#define _kt_tacocat_receive_step_check_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the check step of a receive request.
+ *
+ * This prints on error.
+ *
+ * @param main
+ * The main program and settings data.
+ *
+ * Must not be NULL.
+ *
+ * This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ * The socket set to process.
+ *
+ * Must not be NULL.
+ *
+ * This alters set.status:
+ * F_okay on success.
+ *
+ * F_first_not (with error bit) on packet is not a 'file' type for the first packet.
+ * F_type_not (with error bit) on parts type not supported.
+ *
+ * Errors (with error bit) from: f_memory_array_increase_by()
+ *
+ * @see f_memory_array_increase_by()
+ */
+#ifndef _di_kt_tacocat_receive_step_check_
+ extern void kt_tacocat_receive_step_check(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // _di_kt_tacocat_receive_step_check_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_receive_step_check_h
--- /dev/null
+#include "../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_tacocat_receive_step_control_
+ f_status_t kt_tacocat_receive_step_control(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+ if (!main || !set) return F_status_set_error(F_parameter);
+ if (F_status_is_error(set->status)) return set->status;
+
+ kt_tacocat_receive_process_control(main, set);
+
+ if (set->buffer.used < kt_tacocat_packet_peek_d || F_status_is_error(set->status)) {
+ if (main->setting.active_receive) {
+ --main->setting.active_receive;
+ }
+
+ return F_complete;
+ }
+
+ // Reset the buffer to allow for reusing and writing to the file in blocks.
+ set->buffer.used = 0;
+
+ // 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);
+
+ if (F_status_is_error(set->status)) {
+ kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, kt_tacocat_receive_s, set->network, set->status, set->name);
+
+ if (set->socket.id_data != -1) {
+ f_file_close_id(&set->socket.id_data);
+ }
+
+ set->step = 0;
+
+ return F_complete_not;
+ }
+
+ set->retry = 0;
+ set->buffer.used = 0;
+ set->step = kt_tacocat_socket_step_receive_packet_e;
+ set->status = F_okay;
+
+ return F_complete_not;
+ }
+#endif // _di_kt_tacocat_receive_step_control_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides receive step control functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_receive_step_control_h
+#define _kt_tacocat_receive_step_control_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the control step of a recieve request.
+ *
+ * This prints on error.
+ *
+ * @param main
+ * The main program and settings data.
+ *
+ * Must not be NULL.
+ *
+ * This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ * The socket set to process.
+ *
+ * Must not be NULL.
+ *
+ * This alters set.status:
+ * F_okay on success.
+ *
+ * Errors (with error bit) from: kt_tacocat_receive_process_control()
+ *
+ * Errors (with error bit) from: f_memory_array_increase_by()
+ *
+ * @return
+ * F_complete on success or failure and entire packet is complete (caller should treat this like F_done).
+ * F_complete_not on success or failure but the remaining steps must be accomplished.
+ *
+ * F_parameter (with error bit) on invalid parameter.
+ *
+ * Errors (with error bit) on existing errors at call.
+ *
+ * @see kt_tacocat_receive_process_control()
+ *
+ * @see f_memory_array_increase_by()
+ */
+#ifndef _di_kt_tacocat_receive_step_control_
+ extern f_status_t kt_tacocat_receive_step_control(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // _di_kt_tacocat_receive_step_control_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_receive_step_control_h
--- /dev/null
+#include "../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_tacocat_receive_step_done_
+ void kt_tacocat_receive_step_done(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+ if (!main || !set || F_status_is_error(set->status)) return;
+
+ kt_tacocat_print_message_receive_operation_complete(&main->program.message, *set);
+
+ f_file_close(&set->file);
+
+ set->step = 0;
+ set->status = F_okay;
+
+ if (main->setting.active_receive) {
+ --main->setting.active_receive;
+ }
+
+ if (set->buffer.size > kt_tacocat_max_maintain_d) {
+ set->buffer.used = 0;
+
+ 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, F_status_debug_source_d, kt_tacocat_receive_s, set->network, set->status, set->name);
+ }
+ }
+ }
+#endif // _di_kt_tacocat_receive_step_done_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides receive step done functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_receive_step_done_h
+#define _kt_tacocat_receive_step_done_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the done step of a receive request.
+ *
+ * This prints on error.
+ *
+ * @param main
+ * The main program and settings data.
+ *
+ * Must not be NULL.
+ *
+ * This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ * The socket set to process.
+ *
+ * Must not be NULL.
+ *
+ * This alters set.status:
+ * F_okay on success.
+ */
+#ifndef _di_kt_tacocat_receive_step_done_
+ extern void kt_tacocat_receive_step_done(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // _di_kt_tacocat_receive_step_done_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_receive_step_done_h
--- /dev/null
+#include "../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_tacocat_receive_step_extract_
+ void kt_tacocat_receive_step_extract(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+ if (!main || !set || F_status_is_error(set->status)) return;
+
+ kt_tacocat_packet_extract(main, set, kt_tacocat_receive_s);
+ if (F_status_is_error(set->status)) return;
+
+ set->step = kt_tacocat_socket_step_receive_check_e;
+ set->status = F_okay;
+ }
+#endif // _di_kt_tacocat_receive_step_extract_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides receive step extract functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_receive_step_extract_h
+#define _kt_tacocat_receive_step_extract_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the extract step of a receive request.
+ *
+ * This prints on error.
+ *
+ * @param main
+ * The main program and settings data.
+ *
+ * Must not be NULL.
+ *
+ * This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ * The socket set to process.
+ *
+ * Must not be NULL.
+ *
+ * This alters set.status:
+ * F_okay on success.
+ *
+ * Errors (with error bit) from: kt_tacocat_packet_extract()
+ *
+ * @see kt_tacocat_packet_extract()
+ */
+#ifndef _di_kt_tacocat_receive_step_extract_
+ extern void kt_tacocat_receive_step_extract(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // _di_kt_tacocat_receive_step_extract_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_receive_step_extract_h
--- /dev/null
+#include "../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_tacocat_receive_step_find_
+ void kt_tacocat_receive_step_find(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+ if (!main || !set || F_status_is_error(set->status)) return;
+
+ set->state.status = F_none;
+
+ fll_fss_payload_read(set->buffer, &set->range, &set->objects, &set->contents, &set->objects_delimits, &set->contents_delimits, &set->comments, &set->state);
+
+ // Note that F_fss_found_object_content_not is not treated as an error because the "payload" section is optional.
+ if (F_status_is_error(set->state.status) && F_status_set_fine(set->state.status) != F_fss_found_object_content_not) {
+ switch (F_status_set_fine(set->state.status)) {
+ case F_okay:
+ case F_okay_eos:
+ case F_okay_stop:
+
+ if (set->buffer.used == set->packet.size) {
+
+ // The packet is fully loaded and there is no "payload" section.
+ set->step = kt_tacocat_socket_step_receive_extract_e;
+ }
+ else {
+
+ // Seek the left-most new line from the current position to ensure that the next pass potentially reads a complete line.
+ while (set->range.start && set->buffer.string[set->range.start] != f_string_eol_s.string[0]) {
+ --set->range.start;
+ } // while
+
+ // No packet is found and is not yet finished loading the data.
+ set->step = kt_tacocat_socket_step_receive_packet_e;
+ }
+
+ break;
+
+ default:
+
+ // Seek the left-most new line from the current position to ensure that the next pass potentially reads a complete line.
+ while (set->range.start && set->buffer.string[set->range.start] != f_string_eol_s.string[0]) {
+ --set->range.start;
+ } // while
+
+ if (set->buffer.used != set->packet.size) {
+ set->step = kt_tacocat_socket_step_receive_packet_e;
+ }
+
+ ++set->retry;
+
+ break;
+ }
+ }
+ else {
+ switch (F_status_set_fine(set->state.status)) {
+ case F_okay:
+ case F_okay_eos:
+ case F_okay_stop:
+ case F_data_not:
+ case F_data_not_eos:
+ case F_data_not_stop:
+ case F_fss_found_object_content_not:
+ set->step = kt_tacocat_socket_step_receive_extract_e;
+
+ break;
+
+ default:
+ ++set->retry;
+
+ break;
+ }
+ }
+
+ set->status = F_status_is_error_not(set->state.status) ? set->state.status : F_okay;
+ }
+#endif // _di_kt_tacocat_receive_step_find_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides receive step find functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_receive_step_find_h
+#define _kt_tacocat_receive_step_find_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the find step of a receive request.
+ *
+ * This searches until it finds the start response packet in order to identify the header section.
+ * The step may be set forward or backward depending on the results of this step.
+ *
+ * This prints on error.
+ *
+ * @param main
+ * The main program and settings data.
+ *
+ * Must not be NULL.
+ *
+ * This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ * The socket set to process.
+ *
+ * Must not be NULL.
+ *
+ * This alters set.status:
+ * F_okay on success.
+ *
+ * Errors (with error bit) from: fll_fss_payload_read()
+ *
+ * @see fll_fss_payload_read()
+ */
+#ifndef _di_kt_tacocat_receive_step_find_
+ extern void kt_tacocat_receive_step_find(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // _di_kt_tacocat_receive_step_find_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_receive_step_find_h
--- /dev/null
+#include "../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_tacocat_receive_step_next_
+ void kt_tacocat_receive_step_next(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+ if (!main || !set || F_status_is_error(set->status)) return;
+
+ // @todo
+
+ set->step = kt_tacocat_socket_step_receive_done_e;
+ set->status = F_okay;
+ }
+#endif // _di_kt_tacocat_receive_step_next_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides receive step next functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_receive_step_next_h
+#define _kt_tacocat_receive_step_next_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the next step of a receive request.
+ *
+ * This prints on error.
+ *
+ * @param main
+ * The main program and settings data.
+ *
+ * Must not be NULL.
+ *
+ * This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ * The socket set to process.
+ *
+ * Must not be NULL.
+ *
+ * This alters set.status:
+ * F_okay on success.
+ */
+#ifndef _di_kt_tacocat_receive_step_next_
+ extern void kt_tacocat_receive_step_next(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // _di_kt_tacocat_receive_step_next_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_receive_step_next_h
--- /dev/null
+#include "../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_tacocat_receive_step_packet_
+ f_status_t kt_tacocat_receive_step_packet(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+ if (!main || !set) return F_status_set_error(F_parameter);
+ if (F_status_is_error(set->status)) return set->status;
+
+ size_t length_read = 0;
+
+ set->status = f_socket_read_stream(&set->socket, 0, (void *) (set->buffer.string + set->buffer.used), &length_read);
+
+ if (F_status_is_error(set->status)) {
+ kt_tacocat_print_error_on(&main->program.error, F_status_debug_source_d, kt_tacocat_receive_s, set->network, set->status, set->name);
+
+ if (set->socket.id_data != -1) {
+ f_file_close_id(&set->socket.id_data);
+ }
+
+ set->step = 0;
+
+ return F_complete_not;
+ }
+
+ if (length_read) {
+ set->retry = 0;
+ set->buffer.used += length_read;
+
+ // This is not a valid packet if the actual size is greater than expected.
+ if (set->buffer.used > set->packet.size) {
+ kt_tacocat_print_error_on_packet_too_large(&main->program.error, kt_tacocat_receive_s, set->network, set->packet.size, set->buffer.used);
+
+ set->status = F_status_set_error(F_packet_too_large);
+
+ return F_complete;
+ }
+
+ // Initialize the range to start reading after the Control and Size blocks.
+ if (set->range.start > set->range.stop) {
+ set->range.start = F_fss_simple_packet_block_header_size_d;
+ }
+
+ set->range.stop = set->buffer.used - 1;
+ set->step = kt_tacocat_socket_step_receive_find_e;
+ }
+ else {
+ ++set->retry;
+ }
+
+ set->status = F_okay;
+
+ return F_complete_not;
+ }
+#endif // _di_kt_tacocat_receive_step_packet_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides receive step packet functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_receive_step_packet_h
+#define _kt_tacocat_receive_step_packet_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the packet step of a receive request.
+ *
+ * This prints on error.
+ *
+ * @param main
+ * The main program and settings data.
+ *
+ * Must not be NULL.
+ *
+ * This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ * The socket set to process.
+ *
+ * Must not be NULL.
+ *
+ * This alters set.status:
+ * F_okay on success.
+ *
+ * F_packet_too_large (with error bit) on the buffer being larged than the allowed packet size.
+ *
+ * Errors (with error bit) from: f_socket_read_stream()
+ *
+ * @return
+ * F_complete on success or failure and entire packet is complete (caller should treat this like F_done).
+ * F_complete_not on success or failure but the remaining steps must be accomplished.
+ *
+ * F_parameter (with error bit) on invalid parameter.
+ *
+ * Errors (with error bit) on existing errors at call.
+ *
+ * @see f_socket_read_stream()
+ */
+#ifndef _di_kt_tacocat_receive_step_packet_
+ extern f_status_t kt_tacocat_receive_step_packet(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // _di_kt_tacocat_receive_step_packet_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_receive_step_packet_h
--- /dev/null
+#include "../../tacocat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_tacocat_receive_step_write_
+ void kt_tacocat_receive_step_write(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set) {
+
+ if (!main || !set || F_status_is_error(set->status)) return;
+
+ set->status = f_file_open(set->name, F_file_mode_all_rw_d, &set->file);
+
+ if (F_status_is_error(set->status)) {
+ kt_tacocat_print_error_on_file_receive(&main->program.error, F_status_debug_source_d, kt_tacocat_receive_s, set->network, set->status, set->name, f_file_operation_open_s);
+
+ return; // @todo consider sending a file error to caller. This should not infinitely attempt to open on failure.
+ }
+
+ set->status = f_file_write_range(set->file, set->buffer, set->packet.payload, 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, F_status_debug_source_d, kt_tacocat_receive_s, set->network, set->status, set->name, f_file_operation_write_s);
+ }
+
+ f_file_close(&set->file);
+
+ set->buffer.used = 0;
+ set->step = kt_tacocat_socket_step_receive_next_e;
+ set->status = F_okay;
+ }
+#endif // _di_kt_tacocat_receive_step_write_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * Kevux Tools - TacocaT
+ *
+ * Project: Kevux Tools
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides receive step write functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_tacocat_receive_step_write_h
+#define _kt_tacocat_receive_step_write_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform the write step of a receive request.
+ *
+ * This prints on error.
+ *
+ * @param main
+ * The main program and settings data.
+ *
+ * Must not be NULL.
+ *
+ * This does not alter main.setting.state.status, except on interrupt signal.
+ * @param set
+ * The socket set to process.
+ *
+ * Must not be NULL.
+ *
+ * This alters set.status:
+ * F_okay on success.
+ *
+ * Errors (with error bit) from: f_file_open()
+ * Errors (with error bit) from: f_file_write_range()
+ *
+ * @see f_file_open()
+ * @see f_file_write_range()
+ */
+#ifndef _di_kt_tacocat_receive_step_write_
+ extern void kt_tacocat_receive_step_write(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
+#endif // _di_kt_tacocat_receive_step_write_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_tacocat_receive_step_write_h
return F_done;
}
- return F_done_not;
+ return F_status_is_error(set->status) ? F_status_set_error(F_data_not) : F_data_not;
}
#endif // _di_kt_tacocat_send_process_
* F_done on success and done processing.
* F_done_not on success but not done processing.
*
+ * F_done (with error bit) on error but done processing.
+ * F_done_not (with error bit) on error and not done processing.
* F_parameter (with error bit) on invalid parameter.
*
* @see f_socket_read_stream()
* F_okay on success.
*
* @return
- * F_complete on success and entire payload is sent.
- * F_complete_not on success and the payload is not entirely sent.
+ * F_complete on success and entire payload is sent.
+ * F_complete_not on success and the payload is not entirely sent.
*
* F_parameter (with error bit) on invalid parameter.
+ *
+ * Errors (with error bit) on existing errors at call.
*/
#ifndef _di_kt_tacocat_send_step_wait_
extern f_status_t kt_tacocat_send_step_wait(kt_tacocat_main_t * const main, kt_tacocat_socket_set_t * const set);
#include <program/kevux/tools/tacocat/main/packet.h>
#include <program/kevux/tools/tacocat/main/process.h>
#include <program/kevux/tools/tacocat/main/receive.h>
+#include <program/kevux/tools/tacocat/main/receive/step/check.h>
+#include <program/kevux/tools/tacocat/main/receive/step/control.h>
+#include <program/kevux/tools/tacocat/main/receive/step/done.h>
+#include <program/kevux/tools/tacocat/main/receive/step/extract.h>
+#include <program/kevux/tools/tacocat/main/receive/step/find.h>
+#include <program/kevux/tools/tacocat/main/receive/step/next.h>
+#include <program/kevux/tools/tacocat/main/receive/step/packet.h>
+#include <program/kevux/tools/tacocat/main/receive/step/write.h>
#include <program/kevux/tools/tacocat/main/send.h>
#include <program/kevux/tools/tacocat/main/send/step/build.h>
#include <program/kevux/tools/tacocat/main/send/step/check.h>