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_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
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
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
* - 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 {
f_fss_iki_text_e,
f_fss_basic_rule_e,
f_fss_payload_e,
+ f_fss_simple_packet_e,
};
#endif // _di_f_fss_codes_
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);
}
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);
// FLL-2 includes.
#include <fll/level_2/error.h>
+#include <fll/level_2/fss/basic_list.h>
#include <fll/level_2/fss/extended.h>
#include <fll/level_2/print.h>
#include <fll/level_2/program.h>
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_
* - 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_
/**
/**
* 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_
}
#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;
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;
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) {
* @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.
* @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.
* @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.
*
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);
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.
# 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\:
--- /dev/null
+# 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) ]
- fss-000c: Iki Text
- fss-000d: Basic Rule
- fss-000e: Payload
+ - fss-000f: Simple Packet