From f2fc5d15808d6a128455e81b3e5d22fe636dec7c Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Wed, 9 Mar 2022 22:51:29 -0600 Subject: [PATCH] Progress: Controller and Control sockets. This also adds a new FSS: FSS-000F (Simple Packet). I decided that this needs its own specific specification to represent it. This further helps make it clear that a Packet is not the same as a Payload. There can still be some confusion because the FSS-000F (Simple Packet) has a Payload Block. That Payload Block contains the FSS-000E (Payload). That FSS-000E (Payload) has a Payload section within itself. This means that there are three different, but very similar (and also related), contexts used for a "payload". To try and avoid this, I refer to the payload in FSS-000F (Simple Packet) as the Payload Block. I refer to the payload in the specifications as the FSS Payload or the FSS-000E (Payload). I refer to the payload within the FSS-000F (Simple Packet) as the Payload Object, the Payload Content, or the payload section. --- build/level_0/settings | 2 +- build/monolithic/settings | 2 +- level_0/f_directory/data/build/settings | 2 +- level_0/f_fss/c/fss/common.h | 2 + level_3/control/c/control.c | 12 +-- level_3/control/c/control.h | 1 + level_3/control/c/private-common.c | 14 +++ level_3/control/c/private-common.h | 40 +++++++- level_3/control/c/private-control.c | 135 ++++++++++++++++++++++--- level_3/control/c/private-control.h | 32 ++++-- level_3/controller/c/control/private-control.c | 2 +- level_3/controller/documents/packet.txt | 4 +- level_3/controller/specifications/packet.txt | 8 +- specifications/fss-000f.txt | 47 +++++++++ specifications/fss.txt | 1 + 15 files changed, 261 insertions(+), 43 deletions(-) create mode 100644 specifications/fss-000f.txt diff --git a/build/level_0/settings b/build/level_0/settings index 746ff50..fedeaef 100644 --- a/build/level_0/settings +++ b/build/level_0/settings @@ -38,7 +38,7 @@ build_sources_library color.c color/common.c build_sources_library console.c console/common.c build_sources_library control_group.c control_group/common.c build_sources_library conversion.c private-conversion.c conversion/common.c -build_sources_library directory.c private-directory.c +build_sources_library directory.c directory/common.c private-directory.c build_sources_library environment.c build_sources_library execute.c build_sources_library file.c file/common.c private-file.c diff --git a/build/monolithic/settings b/build/monolithic/settings index 5af63af..eb6c0fa 100644 --- a/build/monolithic/settings +++ b/build/monolithic/settings @@ -38,7 +38,7 @@ build_sources_library level_0/color.c level_0/color/common.c build_sources_library level_0/console.c level_0/console/common.c build_sources_library level_0/control_group.c level_0/control_group/common.c build_sources_library level_0/conversion.c level_0/private-conversion.c level_0/conversion/common.c -build_sources_library level_0/directory.c level_0/private-directory.c +build_sources_library level_0/directory.c level_0/directory/common.c level_0/private-directory.c build_sources_library level_0/environment.c build_sources_library level_0/execute.c build_sources_library level_0/file.c level_0/file/common.c level_0/private-file.c diff --git a/level_0/f_directory/data/build/settings b/level_0/f_directory/data/build/settings index 378fcb9..cddf056 100644 --- a/level_0/f_directory/data/build/settings +++ b/level_0/f_directory/data/build/settings @@ -31,7 +31,7 @@ build_objects_library_static build_objects_program build_objects_program_shared build_objects_program_static -build_sources_library directory.c private-directory.c directory/common.c +build_sources_library directory.c directory/common.c private-directory.c build_sources_library_shared build_sources_library_static build_sources_object diff --git a/level_0/f_fss/c/fss/common.h b/level_0/f_fss/c/fss/common.h index 23ccadf..6fc61a7 100644 --- a/level_0/f_fss/c/fss/common.h +++ b/level_0/f_fss/c/fss/common.h @@ -150,6 +150,7 @@ extern "C" { * - iki_text: FSS-000C: IKI Text. * - basic_rule: FSS-000D: Basic Rule. * - payload: FSS-000E: Payload. + * - simple_packet: FSS-000F: Simple Packet. */ #ifndef _di_f_fss_codes_ enum { @@ -168,6 +169,7 @@ extern "C" { f_fss_iki_text_e, f_fss_basic_rule_e, f_fss_payload_e, + f_fss_simple_packet_e, }; #endif // _di_f_fss_codes_ diff --git a/level_3/control/c/control.c b/level_3/control/c/control.c index 7c9feaf..dc49685 100644 --- a/level_3/control/c/control.c +++ b/level_3/control/c/control.c @@ -214,14 +214,14 @@ extern "C" { status = control_settings_load(main, &data); if (F_status_is_error_not(status)) { - status = control_payload_build(main, &data); + status = control_packet_build(main, &data); if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_too_large) { control_print_error_request_packet_too_large(main); } else { - fll_error_print(main->error, F_status_set_fine(status), "control_payload_build", F_true); + fll_error_print(main->error, F_status_set_fine(status), "control_packet_build", F_true); } fll_print_dynamic_raw(f_string_eol_s, main->error.to.stream); @@ -229,23 +229,23 @@ extern "C" { } if (F_status_is_error_not(status)) { - status = control_payload_send(main, &data); + status = control_packet_send(main, &data); if (F_status_is_error(status)) { - fll_error_print(main->error, F_status_set_fine(status), "control_payload_send", F_true); + fll_error_print(main->error, F_status_set_fine(status), "control_packet_send", F_true); fll_print_dynamic_raw(f_string_eol_s, main->error.to.stream); } } if (F_status_is_error_not(status)) { - status = control_payload_receive(main, &data); + status = control_packet_receive(main, &data); if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_too_large) { control_print_error_response_packet_valid_not(main); } else { - fll_error_print(main->error, F_status_set_fine(status), "control_payload_receive", F_true); + fll_error_print(main->error, F_status_set_fine(status), "control_packet_receive", F_true); } fll_print_dynamic_raw(f_string_eol_s, main->error.to.stream); diff --git a/level_3/control/c/control.h b/level_3/control/c/control.h index 1d193f0..b82714a 100644 --- a/level_3/control/c/control.h +++ b/level_3/control/c/control.h @@ -40,6 +40,7 @@ // FLL-2 includes. #include +#include #include #include #include diff --git a/level_3/control/c/private-common.c b/level_3/control/c/private-common.c index f619a29..2e82422 100644 --- a/level_3/control/c/private-common.c +++ b/level_3/control/c/private-common.c @@ -47,6 +47,20 @@ extern "C" { f_string_dynamic_resize(0, &data->cache.large); f_string_dynamic_resize(0, &data->cache.small); + f_string_dynamic_resize(0, &data->cache.payload); + + f_string_ranges_resize(0, &data->cache.packet_objects); + f_string_rangess_resize(0, &data->cache.packet_contents); + + f_string_ranges_resize(0, &data->cache.payload_objects); + f_string_rangess_resize(0, &data->cache.payload_contents); + + f_array_lengths_resize(0, &data->cache.delimits); + + f_string_ranges_resize(0, &data->cache.range_actions); + f_string_ranges_resize(0, &data->cache.range_statuss); + + f_uint8s_resize(0, &data->cache.types); } #endif // _di_control_data_delete_ diff --git a/level_3/control/c/private-common.h b/level_3/control/c/private-common.h index 765fe41..36fd0ea 100644 --- a/level_3/control/c/private-common.h +++ b/level_3/control/c/private-common.h @@ -44,8 +44,8 @@ extern "C" { * - endian_big: Designate that the packet is in big endian order (when not set then packet is in little endian order). */ #ifndef _di_control_packet_flag_ - #define control_packet_flag_binary_d 0x10000000 - #define control_packet_flag_endian_big_d 0x01000000 + #define control_packet_flag_binary_d 0x80 + #define control_packet_flag_endian_big_d 0x40 #endif // _di_control_packet_flag_ /** @@ -241,19 +241,51 @@ extern "C" { /** * The control cache. * - * large: A buffer for storing large sets of data. - * small: A buffer for storing small sets of data. + * large: A buffer for storing large sets of data. + * small: A buffer for storing small sets of data. + * payload: A buffer dedicated for the payload. + * + * packet_objects: The FSS Objects for a packet. + * packet_contents: The FSS Contents for a packet. + * + * payload_objects: The FSS Objects for a payload. + * payload_contents: The FSS Contents for a payload. + * + * delimits: The delimits cache. */ #ifndef _di_control_cache_t_ typedef struct { f_string_dynamic_t large; f_string_dynamic_t small; + f_string_dynamic_t payload; + + f_fss_objects_t packet_objects; + f_fss_contents_t packet_contents; + + f_fss_objects_t payload_objects; + f_fss_contents_t payload_contents; + + f_fss_delimits_t delimits; + + f_string_ranges_t range_actions; + f_string_ranges_t range_statuss; + + f_uint8s_t types; } control_cache_t; #define control_cache_initialize \ { \ f_string_dynamic_t_initialize, \ f_string_dynamic_t_initialize, \ + f_string_dynamic_t_initialize, \ + f_fss_objects_t_initialize, \ + f_fss_contents_t_initialize, \ + f_fss_objects_t_initialize, \ + f_fss_contents_t_initialize, \ + f_fss_delimits_t_initialize, \ + f_string_ranges_t_initialize, \ + f_string_ranges_t_initialize, \ + f_uint8s_t_initialize, \ } #endif // _di_control_cache_t_ diff --git a/level_3/control/c/private-control.c b/level_3/control/c/private-control.c index 57fecc2..532e229 100644 --- a/level_3/control/c/private-control.c +++ b/level_3/control/c/private-control.c @@ -146,8 +146,8 @@ extern "C" { } #endif // _di_control_command_verify_ -#ifndef _di_control_payload_build_ - f_status_t control_payload_build(fll_program_data_t * const main, control_data_t * const data) { +#ifndef _di_control_packet_build_ + f_status_t control_packet_build(fll_program_data_t * const main, control_data_t * const data) { data->cache.large.used = 0; data->cache.small.used = 0; @@ -253,35 +253,140 @@ extern "C" { return F_none; } -#endif // _di_control_payload_build_ +#endif // _di_control_packet_build_ -#ifndef _di_control_payload_receive_ - f_status_t control_payload_receive(fll_program_data_t * const main, control_data_t * const data) { +#ifndef _di_control_packet_receive_ + f_status_t control_packet_receive(fll_program_data_t * const main, control_data_t * const data) { data->cache.large.used = 0; data->cache.small.used = 0; + data->cache.packet_objects.used = 0; + data->cache.packet_contents.used = 0; + data->cache.payload_objects.used = 0; + data->cache.payload_contents.used = 0; + data->cache.delimits.used = 0; + data->cache.range_actions.used = 0; + data->cache.range_statuss.used = 0; + data->cache.types.used = 0; - uint8_t control = 0; + f_status_t status = F_none; + f_array_length_t length = 5; { - f_array_length_t length = 5; - - f_char_t head[length]; + uint8_t head[length]; - memset(head, 0, sizeof(f_char_t) * length); + memset(head, 0, sizeof(uint8_t) * length); - f_status_t status = f_socket_read(&data->socket, 0, (void *) head, &length); + status = f_socket_read(&data->socket, f_socket_flag_peek_d, (void *) head, &length); if (F_status_is_error(status)) return status; if (length < 5) return F_status_set_error(F_packet_not); + + uint8_t control = head[0] & (control_packet_flag_binary_d | control_packet_flag_endian_big_d); + + // Only the first two bits of the 8 Control bits are allowed to be set to 1 for this Packet. + if (head[0] & (~(control_packet_flag_binary_d | control_packet_flag_endian_big_d))) { + return F_status_set_error(F_packet_not); + } + + #ifdef _is_F_endian_big + if (control & control_packet_flag_endian_big_d) { + length = ((uint8_t) head[1]) << 24; + length |= ((uint8_t) head[2]) << 16; + length |= ((uint8_t) head[3]) << 8; + length |= (uint8_t) head[4]; + } + else { + length = ((uint8_t) head[1]); + length |= ((uint8_t) head[2]) >> 8; + length |= ((uint8_t) head[3]) >> 16; + length |= (uint8_t) head[4] >> 24; + } + #else + if (control & control_packet_flag_endian_big_d) { + length = ((uint8_t) head[1]); + length |= ((uint8_t) head[2]) >> 8; + length |= ((uint8_t) head[3]) >> 16; + length |= (uint8_t) head[4] >> 24; + } + else { + length = ((uint8_t) head[1]) << 24; + length |= ((uint8_t) head[2]) << 16; + length |= ((uint8_t) head[3]) << 8; + length |= (uint8_t) head[4]; + } + #endif // #ifdef _is_F_endian_big + + if (length > 0xffffffff) { + return F_status_set_error(F_too_large); + } + + status = f_string_dynamic_increase_by(length, &data->cache.large); + if (F_status_is_error(status)) return status; + + status = f_socket_read(&data->socket, f_socket_flag_wait_all_d, (void *) head, &length); + if (F_status_is_error(status)) return status; + if (length < data->cache.large.used) return F_status_set_error(F_too_small); + if (length > data->cache.large.used) return F_status_set_error(F_too_large); + } + + { + f_state_t state = macro_f_state_t_initialize(control_allocation_large_d, control_allocation_small_d, 0, &control_signal_state_interrupt_fss, 0, (void *) main, 0); + f_string_range_t range_packet = macro_f_string_range_t_initialize(data->cache.large.used); + + status = fll_fss_basic_list_read(data->cache.large, state, &range_packet, &data->cache.packet_objects, &data->cache.packet_contents, &data->cache.delimits, 0, 0); + if (F_status_is_error(status)) return status; + + status = fl_fss_apply_delimit(data->cache.delimits, &data->cache.large); + if (F_status_is_error(status)) return status; + + data->cache.delimits.used = 0; + + f_string_range_t *range_header_object = 0; + f_string_ranges_t *range_header_content = 0; + f_string_range_t *range_payload_object = 0; + f_string_ranges_t *range_payload_content = 0; + + for (f_array_length_t i = 0; i < data->cache.packet_objects.used; ++i) { + + if (fl_string_dynamic_partial_compare_string(f_fss_string_header_s.string, data->cache.large, f_fss_string_header_s.used, data->cache.packet_objects.array[i]) == F_equal_to) { + + // The FSS-000E (Payload) standard does not prohibit multiple "header", but such cases are not supported by the controller and the control programs. + if (range_header_object) { + return F_status_set_error(F_packet_not); + } + + range_header_object = &data->cache.packet_objects.array[i]; + range_header_content = &data->cache.packet_contents.array[i]; + } + else if (fl_string_dynamic_partial_compare_string(f_fss_string_payload_s.string, data->cache.large, f_fss_string_payload_s.used, data->cache.packet_objects.array[i]) == F_equal_to) { + + // Only a single "payload" is supported by the FSS-000E (Payload) standard. + if (range_payload_object) { + return F_status_set_error(F_packet_not); + } + + range_payload_object = &data->cache.packet_objects.array[i]; + range_payload_content = &data->cache.packet_contents.array[i]; + } + } // for + + if (!range_header_object || !range_payload_object) { + return F_status_set_error(F_packet_not); + } + + // @todo load the "action"s, "length", "status"s, "type"s, and finally the "payload" (if lenth is > 0). + + //status = fll_fss_extended_read(data->cache.payload, state, range_payload_content, &data->cache.payload_objects, &data->cache.payload_contents, &data->cache.delimits, 0, 0); + //if (F_status_is_error(status)) return status; } // @todo return F_none; } -#endif // _di_control_payload_receive_ +#endif // _di_control_packet_receive_ -#ifndef _di_control_payload_send_ - f_status_t control_payload_send(fll_program_data_t * const main, control_data_t * const data) { +#ifndef _di_control_packet_send_ + f_status_t control_packet_send(fll_program_data_t * const main, control_data_t * const data) { // @todo f_array_length_t length = 0; @@ -290,7 +395,7 @@ extern "C" { return F_none; } -#endif // _di_control_payload_send_ +#endif // _di_control_packet_send_ #ifndef _di_control_settings_load_ f_status_t control_settings_load(fll_program_data_t * const main, control_data_t * const data) { diff --git a/level_3/control/c/private-control.h b/level_3/control/c/private-control.h index 50c0798..a628109 100644 --- a/level_3/control/c/private-control.h +++ b/level_3/control/c/private-control.h @@ -64,9 +64,9 @@ extern "C" { * @see f_string_dynamic_append() * @see f_string_dynamic_resize() */ -#ifndef _di_control_payload_build_ - extern f_status_t control_payload_build(fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d; -#endif // _di_control_payload_build_ +#ifndef _di_control_packet_build_ + extern f_status_t control_packet_build(fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d; +#endif // _di_control_packet_build_ /** * Receive the response from the remote socket, storing it in the large cache. @@ -79,17 +79,29 @@ extern "C" { * @return * F_none on success. * - * F_packet_not (with error bit) If the received packet is not a valid packet. + * F_packet_not (with error bit) If the received packet is not a valid packet or not a supported packet structure. + * F_too_large (with error bit) If the received packet specifies a size that is too large or the actual size is larger than the specified size. + * F_too_small (with error bit) If the received packet actual size is smaller than the specified size. * + * Errors (with error bit) from: f_socket_read(). * Errors (with error bit) from: f_string_dynamic_append(). + * Errors (with error bit) from: f_string_dynamic_increase_by(). * Errors (with error bit) from: f_string_dynamic_resize(). + * Errors (with error bit) from: fl_fss_apply_delimit(). + * Errors (with error bit) from: fll_fss_basic_list_read(). + * Errors (with error bit) from: fll_fss_extended_read(). * + * @see f_socket_read() * @see f_string_dynamic_append() + * @see f_string_dynamic_increase_by() * @see f_string_dynamic_resize() + * @see fl_fss_apply_delimit() + * @see fll_fss_basic_list_read() + * @see fll_fss_extended_read() */ -#ifndef _di_control_payload_receive_ - extern f_status_t control_payload_receive(fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d; -#endif // _di_control_payload_receive_ +#ifndef _di_control_packet_receive_ + extern f_status_t control_packet_receive(fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d; +#endif // _di_control_packet_receive_ /** * Send the payload to the remote socket, getting the payload from the large cache. @@ -99,9 +111,9 @@ extern "C" { * @param data * The control data. */ -#ifndef _di_control_payload_send_ - extern f_status_t control_payload_send(fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d; -#endif // _di_control_payload_send_ +#ifndef _di_control_packet_send_ + extern f_status_t control_packet_send(fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d; +#endif // _di_control_packet_send_ /** * Load and process the control settings file. * diff --git a/level_3/controller/c/control/private-control.c b/level_3/controller/c/control/private-control.c index 135a40b..80f5bee 100644 --- a/level_3/controller/c/control/private-control.c +++ b/level_3/controller/c/control/private-control.c @@ -78,7 +78,7 @@ extern "C" { return F_valid_not; } - // @todo rewrite based on control_payload_build(), but need to pre-process what is needed for the payload. + // @todo rewrite based on control_packet_build(), but need to pre-process what is needed for the payload. const uint8_t packet_flag = controller_control_packet_header_flag(buffer); const uint32_t packet_length = controller_control_packet_header_length(packet_flag & controller_control_packet_flag_endian_big_d, buffer); diff --git a/level_3/controller/documents/packet.txt b/level_3/controller/documents/packet.txt index 3e89851..7016fe2 100644 --- a/level_3/controller/documents/packet.txt +++ b/level_3/controller/documents/packet.txt @@ -21,11 +21,11 @@ Packet Documentation: This number is a single 32-bit unsigned integer. Example packet structure\: - [ control block ] [ size block ] [ payload block ] + [ Control Block ] [ Size Block ] [ Payload Block ] [ 0b10000000 ] [ 0b00000000 0b00000000 0b00000100 0b11010010 ] [ size: 1229 (1234 - 5) ] The payload block\: - This block is represented by the FSS-000e payload specification and its structure ad use is described in the next sections. + This block is represented by the FSS-000E payload specification and its structure ad use is described in the next sections. The following types of payload are received or sent\: 1) controller payload. diff --git a/level_3/controller/specifications/packet.txt b/level_3/controller/specifications/packet.txt index 25ade85..ba737a3 100644 --- a/level_3/controller/specifications/packet.txt +++ b/level_3/controller/specifications/packet.txt @@ -3,8 +3,12 @@ # license: open-standard-license-1.0 # -Entry Specification: - The controller program communicates use the FSS-000E Packet format. +Packet Specification: + The controller program communicates use the FSS-000F (Packet). + This specification declares how the Payload Block, which is in FSS-000E (Payload) format, is required to be used. + + Only a single "header" is allowed. + Only a single "payload" is allowed. Packet Structure\: Packet is grouped into the following blocks\: diff --git a/specifications/fss-000f.txt b/specifications/fss-000f.txt new file mode 100644 index 0000000..03ab964 --- /dev/null +++ b/specifications/fss-000f.txt @@ -0,0 +1,47 @@ +# fss-0002 +# +# license: open-standard-license-1.0 +# +# + +Featureless Settings Specification: 000f - Simple Packet: + This is a network packet format that contains FSS-000E (Payload) within it. + + The Simple Packet structure is described in blocks, of which are structured in bytes. + + There are only three blocks in this format\: + 1) Control Block. + 2) Size Block. + 3) Payload Block. + + The Control Block is the first block in the packet and is considered endianless. + There exists only a single byte within the Control Block. + Regardless of the endianness of the packet, the leftmost bit is always the "string" or "binary" bit. + The second bit following that bit represents the endianness bit. + + The "string" or "binary" bit, a value of 0 designates that the packet is in string format and a value of 1 designates that the packet is in binary format. + While the packet might be considered to be in string format, it is technically always in binary format due to the Control Block and Size Block. + This means that the bit designating the packet as a "string" packet or a "binary" packet is referring to whether or not the Payload Block is in "string" format or is in "binary" format. + + The endianness bit designates whether or not the packet is in big endian or little endian format. + A bit value of 0 designates that this packet is in little endian and a value of 1 designates that this packet is in big endian format. + All binary data within this packet, following the Control Block, must respect this endianness bit (including the Size Block). + + The remaining bits are not defined by this standard and are expected to be 0. + Non-formal or local uses may utilize these remaining 6 bits as desired. + However, there may be additional standards that expand upon this and utilize these remaining Control bits. + Anything that utilizes these unused Control bits may add or remove additional Blocks after the Control Block as they see fit. + + The Size Block is an unsigned 32-bit integer representing the size of the entire packet, including the Control Block and Size Block. + This size must exactly match the packet to be a valid packet. + The size represents number of bytes in the file. + The Control Block is 1 byte long and the Size Block is 4 bytes long and so the maximum available size is (2^32)-6. + + The Payload Block is not defined by this standard of that that it exists and should be in FSS-000E (Payload) format. + The FSS-000E (Payload) may be represented in either string format or binary format. + The FSS-000E (Payload) may contain multiple "header"s but may only contain a single "payload". + With this in mind, it is recommended that only a single "header" be supported in the Payload Block. + + Example Packet Structure\: + [ Control Block ] [ Size Block ] [ Payload Block ] + [ 0b10000000 ] [ 0b00000000 0b00000000 0b00000100 0b11010010 ] [ size: 1229 (1234 - 5) ] diff --git a/specifications/fss.txt b/specifications/fss.txt index 6841862..06bf0f9 100644 --- a/specifications/fss.txt +++ b/specifications/fss.txt @@ -145,3 +145,4 @@ Featureless Settings Specifications: - fss-000c: Iki Text - fss-000d: Basic Rule - fss-000e: Payload + - fss-000f: Simple Packet -- 1.8.3.1