Implements the processing of the Header.
fl_conversion
fl_fss
fl_print
+fl_status_string
fll_error
fll_fss
build_language c
build_libraries -lc
-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_random -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
+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_thread -lf_thread
build_libraries-level -lfll_2 -lfll_1 -lfll_0
build_libraries-monolithic -lfll
#endif // _di_kt_tacocat_parameter_e_
/**
+ * Types of packets.
+ *
+ * kt_tacocat_print_flag_*_e:
+ * - none: No type is set.
+ * - done: The package concludes the connection (from the sender or receiver) or acknowledges the receipt of a packet (receiver).
+ * - file: The packet is a file.
+ * - next: The packet is a request for the next file.
+ * - resend: The packet is a request to resend the given part number.
+ */
+#ifndef _di_kt_tacocat_print_flag_e_
+ enum {
+ kt_tacocat_packet_type_none_e = 0x0,
+ kt_tacocat_packet_type_done_e = 0x1,
+ kt_tacocat_packet_type_file_e = 0x2,
+ kt_tacocat_packet_type_next_e = 0x4,
+ kt_tacocat_packet_type_resend_e = 0x8,
+ }; // enum
+#endif // _di_kt_tacocat_print_flag_e_
+
+/**
* Flags for fine-tuned print control.
*
* kt_tacocat_print_flag_*_e:
"fl_conversion_dynamic_partial_to_unsigned_detect",
"fl_conversion_dynamic_to_unsigned_detect",
"fl_fss_payload_header_map",
+ "fl_status_string_from",
"fll_fss_extended_read",
"fll_fss_payload_read",
"fll_program_parameter_process_context",
kt_tacocat_f_fl_conversion_dynamic_partial_to_unsigned_detect_e,
kt_tacocat_f_fl_conversion_dynamic_to_unsigned_detect_e,
kt_tacocat_f_fl_fss_payload_header_map_e,
+ kt_tacocat_f_fl_status_string_from_e,
kt_tacocat_f_fll_fss_extended_read_e,
kt_tacocat_f_fll_fss_payload_read_e,
kt_tacocat_f_fll_program_parameter_process_context_e,
#ifndef _di_kt_tacocat_s_
const f_string_static_t kt_tacocat_classic_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_classic_s, 0, KT_TACOCAT_classic_s_length);
const f_string_static_t kt_tacocat_digit_negative_one_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_digit_negative_one_s, 0, KT_TACOCAT_digit_negative_one_s_length);
+ const f_string_static_t kt_tacocat_done_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_done_s, 0, KT_TACOCAT_done_s_length);
const f_string_static_t kt_tacocat_kevux_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_kevux_s, 0, KT_TACOCAT_kevux_s_length);
const f_string_static_t kt_tacocat_file_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_file_s, 0, KT_TACOCAT_file_s_length);
const f_string_static_t kt_tacocat_network_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_network_s, 0, KT_TACOCAT_network_s_length);
const f_string_static_t kt_tacocat_network_or_socket_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_network_or_socket_s, 0, KT_TACOCAT_network_or_socket_s_length);
+ const f_string_static_t kt_tacocat_next_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_next_s, 0, KT_TACOCAT_next_s_length);
const f_string_static_t kt_tacocat_receive_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_receive_s, 0, KT_TACOCAT_receive_s_length);
+ const f_string_static_t kt_tacocat_resend_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_resend_s, 0, KT_TACOCAT_resend_s_length);
const f_string_static_t kt_tacocat_salt_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_salt_s, 0, KT_TACOCAT_salt_s_length);
const f_string_static_t kt_tacocat_send_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_send_s, 0, KT_TACOCAT_send_s_length);
const f_string_static_t kt_tacocat_send_build_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_send_build_s, 0, KT_TACOCAT_send_build_s_length);
#ifndef _di_kt_tacocat_s_
#define KT_TACOCAT_classic_s "classic"
#define KT_TACOCAT_digit_negative_one_s "-1"
- #define KT_TACOCAT_kevux_s "kevux"
+ #define KT_TACOCAT_done_s "done"
#define KT_TACOCAT_file_s "file"
+ #define KT_TACOCAT_kevux_s "kevux"
#define KT_TACOCAT_network_s "network"
#define KT_TACOCAT_network_or_socket_s "network / socket"
+ #define KT_TACOCAT_next_s "next"
#define KT_TACOCAT_receive_s "receive"
+ #define KT_TACOCAT_resend_s "resend"
#define KT_TACOCAT_salt_s "salt"
#define KT_TACOCAT_send_s "send"
#define KT_TACOCAT_send_build_s "send build"
#define KT_TACOCAT_classic_s_length 7
#define KT_TACOCAT_digit_negative_one_s_length 2
- #define KT_TACOCAT_kevux_s_length 5
+ #define KT_TACOCAT_done_s_length 4
#define KT_TACOCAT_file_s_length 4
+ #define KT_TACOCAT_kevux_s_length 5
#define KT_TACOCAT_network_s_length 7
#define KT_TACOCAT_network_or_socket_s_length 16
+ #define KT_TACOCAT_next_s_length 4
#define KT_TACOCAT_receive_s_length 7
+ #define KT_TACOCAT_resend_s_length 6
#define KT_TACOCAT_salt_s_length 4
#define KT_TACOCAT_send_s_length 4
#define KT_TACOCAT_send_build_s_length 19
extern const f_string_static_t kt_tacocat_classic_s;
extern const f_string_static_t kt_tacocat_digit_negative_one_s;
+ extern const f_string_static_t kt_tacocat_done_s;
extern const f_string_static_t kt_tacocat_kevux_s;
extern const f_string_static_t kt_tacocat_file_s;
extern const f_string_static_t kt_tacocat_network_s;
extern const f_string_static_t kt_tacocat_network_or_socket_s;
+ extern const f_string_static_t kt_tacocat_next_s;
extern const f_string_static_t kt_tacocat_receive_s;
+ extern const f_string_static_t kt_tacocat_resend_s;
extern const f_string_static_t kt_tacocat_salt_s;
extern const f_string_static_t kt_tacocat_send_s;
extern const f_string_static_t kt_tacocat_send_build_s;
}
#endif // _di_kt_tacocat_print_error_on_file_send_
+#ifndef _di_kt_tacocat_print_error_on_packet_header_value_invalid_
+ f_status_t kt_tacocat_print_error_on_packet_header_value_invalid(fl_print_t * const print, const f_string_static_t on, const f_string_static_t network, const f_status_t status, const f_string_static_t name, const f_string_static_t buffer, const f_range_t object, const f_range_t content) {
+
+ if (!print) return F_status_set_error(F_output_not);
+ if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
+
+ f_file_stream_lock(print->to);
+
+ fl_print_format("%[%QNetwork packet header on%] ", print->to, print->set->error, print->prefix, print->set->error);
+ fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, on, print->set->notable);
+ fl_print_format(" %[for '%]", 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, network, print->set->notable);
+ 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("%[' 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("%[' 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);
+
+ f_file_stream_unlock(print->to);
+
+ return F_okay;
+ }
+#endif // _di_kt_tacocat_print_error_on_packet_header_value_invalid_
+
#ifndef _di_kt_tacocat_print_error_on_packet_invalid_
f_status_t kt_tacocat_print_error_on_packet_invalid(fl_print_t * const print, const f_string_static_t on, const f_string_static_t network) {
#endif // _di_kt_tacocat_print_error_on_file_send_
/**
+ * Print network-related error message for when a packet has an invalid header Object and Content.
+ *
+ * @param print
+ * The output structure to print to.
+ *
+ * This does not alter print.custom.setting.state.status.
+ * @param on
+ * The network connection direction, which should either be "receive" or "send".
+ * @param network
+ * The name of the network in which the error is related.
+ * @param status
+ * The status code representing the error.
+ * @param name
+ * The name of the file.
+ * @param buffer
+ * The buffer containing the entire header.
+ * @param object
+ * The range in the buffer representing the header Object with the error.
+ * @param content
+ * The range in the buffer representing the header Content with the error.
+ *
+ * @return
+ * F_okay on success.
+ * F_output_not on success, but no printing is performed.
+ *
+ * F_output_not (with error bit) if setting is NULL.
+ *
+ * @see fll_error_file_print()
+ */
+#ifndef _di_kt_tacocat_print_error_on_packet_header_value_invalid_
+ extern f_status_t kt_tacocat_print_error_on_packet_header_value_invalid(fl_print_t * const print, const f_string_static_t on, const f_string_static_t network, const f_status_t status, const f_string_static_t name, const f_string_static_t buffer, const f_range_t object, const f_range_t content);
+#endif // _di_kt_tacocat_print_error_on_packet_header_value_invalid_
+
+/**
* Print network-related error message for when a packet is invalid.
*
* @param print
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;
return;
}
- for (f_number_unsigned_t i = 0; i < set->objects_header.used; ++i) {
+ 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;
+ set->abstruses.array[1].value.type = f_abstruse_none_e;
continue;
}
- set->abstruses.array[0].key = f_fss_payload_object_type_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];
+ 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.
// Require Content to exist.
if (!set->contents_header.array[i].used) {
- set->abstruses.array[1].value.type = f_abstruse_none_e;
+ set->abstruses.array[2].value.type = f_abstruse_none_e;
continue;
}
- set->abstruses.array[1].key = f_fss_payload_object_length_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];
+ 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.
// Require Content to exist.
if (!set->contents_header.array[i].used) {
- set->abstruses.array[2].value.type = f_abstruse_none_e;
+ set->abstruses.array[3].value.type = f_abstruse_none_e;
continue;
}
- set->abstruses.array[2].key = f_fss_payload_object_part_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];
+ 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).
// Require Content to exist.
if (!set->contents_header.array[i].used) {
- set->abstruses.array[3].value.type = f_abstruse_none_e;
+ set->abstruses.array[4].value.type = f_abstruse_none_e;
continue;
}
- set->abstruses.array[3].key = f_fss_payload_object_total_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];
+ 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).
// Require Content to exist.
if (!set->contents_header.array[i].used) {
- set->abstruses.array[4].value.type = f_abstruse_none_e;
+ set->abstruses.array[5].value.type = f_abstruse_none_e;
continue;
}
- set->abstruses.array[4].key = f_fss_payload_object_name_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];
+ 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 5 is the name (file name).
+ // 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[5].value.type = f_abstruse_none_e;
+ set->abstruses.array[6].value.type = f_abstruse_none_e;
continue;
}
- set->abstruses.array[5].key = kt_tacocat_salt_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];
+ 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;
}
* 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.
#include <fll/level_1/fss.h>
#include <fll/level_1/fss/payload.h>
#include <fll/level_1/print.h>
+#include <fll/level_1/status_string.h>
// FLL-2 includes.
#include <fll/level_2/error.h>