This focuses on the control end of things.
This pulls in several dependencies that are needed to process the packet.
fll_program_print_help_option(main->output.to, main->context, control_short_settings_s, control_long_settings_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Specify a directory path or a full path to the control settings file.");
fll_program_print_help_option(main->output.to, main->context, control_short_socket_s, control_long_socket_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a directory path or a full path to the controller socket file.");
- fll_program_print_help_usage(main->output.to, main->context, control_program_name_s, control_command_s);
+ fll_program_print_help_usage(main->output.to, main->context, control_program_name_s, control_action_s);
fl_print_format(" When the %[%r%r%] parameter represents a directory path then the file name is generated from either the", main->output.to.stream, main->context.set.notable, f_console_symbol_long_enable_s, control_long_socket_s, main->context.set.notable);
fl_print_format(" %[%r%r%] parameter or from the control settings file.%r%r", main->output.to.stream, main->context.set.notable, f_console_symbol_long_enable_s, control_long_name_s, main->context.set.notable, f_string_eol_s, f_string_eol_s);
control_data_t data = control_data_t_initialize;
data.argv = main->parameters.arguments.array;
- // Verify commands before attempting to connect to the socket.
- if (control_command_identify(main, &data, data.argv[main->parameters.remaining.array[0]]) == F_found) {
- status = control_command_verify(main, &data);
+ data.action = control_action_identify(main, &data, data.argv[main->parameters.remaining.array[0]]);
+
+ if (data.action) {
+ status = control_action_verify(main, &data);
}
else {
- control_print_error_parameter_command_not(main, data.argv[main->parameters.remaining.array[0]]);
+ control_print_error_parameter_action_not(main, data.argv[main->parameters.remaining.array[0]]);
status = F_status_set_error(F_parameter);
}
}
if (F_status_is_error_not(status)) {
- status = control_packet_receive(main, &data);
+ control_payload_header_t header = control_payload_header_t_initialize;
+
+ status = control_packet_receive(main, &data, &header);
if (F_status_is_error(status)) {
if (F_status_set_fine(status) == F_too_large) {
control_data_delete(&data);
}
else {
- control_print_error_parameter_commands_none(main);
+ control_print_error_parameter_actions_none(main);
status = F_status_set_error(F_data_not);
}
#include <fll/level_0/utf.h>
#include <fll/level_0/color.h>
#include <fll/level_0/console.h>
+#include <fll/level_0/conversion.h>
#include <fll/level_0/directory.h>
#include <fll/level_0/file.h>
#include <fll/level_0/fss.h>
#include <fll/level_0/print.h>
#include <fll/level_0/signal.h>
#include <fll/level_0/socket.h>
+#include <fll/level_0/status_string.h>
// FLL-1 includes.
+#include <fll/level_1/conversion.h>
#include <fll/level_1/fss.h>
#include <fll/level_1/print.h>
#include <fll/level_1/string.h>
#include <fll/level_2/fss/extended.h>
#include <fll/level_2/print.h>
#include <fll/level_2/program.h>
+#include <fll/level_2/status_string.h>
// Control includes.
#include <program/control/common.h>
const f_string_static_t control_path_settings_s = macro_f_string_static_t_initialize(CONTROL_path_settings_s, 0, CONTROL_path_settings_s_length);
const f_string_static_t control_action_s = macro_f_string_static_t_initialize(CONTROL_action_s, 0, CONTROL_action_s_length);
- const f_string_static_t control_command_s = macro_f_string_static_t_initialize(CONTROL_command_s, 0, CONTROL_command_s_length);
+ const f_string_static_t control_controller_s = macro_f_string_static_t_initialize(CONTROL_controller_s, 0, CONTROL_controller_s_length);
const f_string_static_t control_default_s = macro_f_string_static_t_initialize(CONTROL_default_s, 0, CONTROL_default_s_length);
+ const f_string_static_t control_error_s = macro_f_string_static_t_initialize(CONTROL_error_s, 0, CONTROL_error_s_length);
const f_string_static_t control_length_s = macro_f_string_static_t_initialize(CONTROL_length_s, 0, CONTROL_length_s_length);
const f_string_static_t control_name_socket_s = macro_f_string_static_t_initialize(CONTROL_name_socket_s, 0, CONTROL_name_socket_s_length);
const f_string_static_t control_path_socket_s = macro_f_string_static_t_initialize(CONTROL_path_socket_s, 0, CONTROL_path_socket_s_length);
const f_string_static_t control_status_s = macro_f_string_static_t_initialize(CONTROL_status_s, 0, CONTROL_status_s_length);
const f_string_static_t control_type_s = macro_f_string_static_t_initialize(CONTROL_type_s, 0, CONTROL_type_s_length);
- const f_string_static_t control_error_s = macro_f_string_static_t_initialize(CONTROL_error_s, 0, CONTROL_error_s_length);
const f_string_static_t control_freeze_s = macro_f_string_static_t_initialize(CONTROL_freeze_s, 0, CONTROL_freeze_s_length);
const f_string_static_t control_kill_s = macro_f_string_static_t_initialize(CONTROL_kill_s, 0, CONTROL_kill_s_length);
const f_string_static_t control_pause_s = macro_f_string_static_t_initialize(CONTROL_pause_s, 0, CONTROL_pause_s_length);
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_string_ranges_resize(0, &data->cache.header_objects);
+ f_string_rangess_resize(0, &data->cache.header_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_
#endif // defined(_override_control_path_settings_) && defined(_override_control_path_settings_length_)
#define CONTROL_action_s "action"
- #define CONTROL_command_s "command"
+ #define CONTROL_controller_s "controller"
#define CONTROL_default_s "default"
+ #define CONTROL_error_s "error"
#define CONTROL_length_s "length"
#define CONTROL_name_socket_s "name_socket"
#define CONTROL_path_socket_s "path_socket"
#define CONTROL_status_s "status"
#define CONTROL_type_s "type"
- #define CONTROL_error_s "error"
#define CONTROL_freeze_s "freeze"
#define CONTROL_kill_s "kill"
#define CONTROL_pause_s "pause"
#define CONTROL_stop_s "stop"
#define CONTROL_thaw_s "thaw"
- #define CONTROL_command_s_length 7
+ #define CONTROL_action_s_length 6
+ #define CONTROL_controller_s_length 10
#define CONTROL_default_s_length 7
+ #define CONTROL_error_s_length 5
+ #define CONTROL_length_s_length 6
#define CONTROL_name_socket_s_length 11
#define CONTROL_path_socket_s_length 11
#define CONTROL_path_socket_prefix_s_length 18
#define CONTROL_path_socket_suffix_s_length 18
- #define CONTROL_type_s_length 4
#define CONTROL_status_s_length 6
- #define CONTROL_length_s_length 6
- #define CONTROL_action_s_length 6
+ #define CONTROL_type_s_length 4
- #define CONTROL_error_s_length 5
#define CONTROL_freeze_s_length 6
#define CONTROL_kill_s_length 4
#define CONTROL_pause_s_length 5
extern const f_string_static_t control_path_settings_s;
extern const f_string_static_t control_action_s;
- extern const f_string_static_t control_command_s;
+ extern const f_string_static_t control_controller_s;
extern const f_string_static_t control_default_s;
+ extern const f_string_static_t control_error_s;
extern const f_string_static_t control_length_s;
extern const f_string_static_t control_name_socket_s;
extern const f_string_static_t control_path_socket_s;
extern const f_string_static_t control_status_s;
extern const f_string_static_t control_type_s;
- extern const f_string_static_t control_error_s;
extern const f_string_static_t control_freeze_s;
extern const f_string_static_t control_kill_s;
extern const f_string_static_t control_pause_s;
#endif // _di_control_strings_s_
/**
- * Codes representing supported commands.
+ * Codes representing supported actions.
*
* freeze: Perform the freeze controller operation.
* kill: Perform the kill controller operation.
* stop: Perform the stop controller operation.
* thaw: Perform the thaw controller operation.
*/
-#ifndef _di_control_command_types_
+#ifndef _di_control_action_types_
enum {
- control_command_type_freeze_e = 1,
- control_command_type_kill_e,
- control_command_type_pause_e,
- control_command_type_reboot_e,
- control_command_type_reload_e,
- control_command_type_rerun_e,
- control_command_type_restart_e,
- control_command_type_resume_e,
- control_command_type_shutdown_e,
- control_command_type_start_e,
- control_command_type_stop_e,
- control_command_type_thaw_e,
+ control_action_type_freeze_e = 1,
+ control_action_type_kill_e,
+ control_action_type_pause_e,
+ control_action_type_reboot_e,
+ control_action_type_reload_e,
+ control_action_type_rerun_e,
+ control_action_type_restart_e,
+ control_action_type_resume_e,
+ control_action_type_shutdown_e,
+ control_action_type_start_e,
+ control_action_type_stop_e,
+ control_action_type_thaw_e,
};
-#endif // _di_control_command_types_
+#endif // _di_control_action_types_
/**
* The control cache.
* 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.
+ * header_objects: The FSS Objects for a packet payload header.
+ * header_contents: The FSS Contents for a packet payload header.
*
* delimits: The delimits cache.
*/
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_objects_t header_objects;
+ f_fss_contents_t header_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_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_
/**
* The control data.
*
- * argv: The argument structure in the progam data parameters for simplifying syntax.
- * command: The command type code.
- * cache: A cache.
- * socket: A socket used to connect to the controller.
+ * argv: The argument structure in the progam data parameters for simplifying syntax.
+ * action: The action type code.
+ * cache: A cache.
+ * socket: A socket used to connect to the controller.
*/
#ifndef _di_control_data_t_
typedef struct {
- uint8_t command;
+ uint8_t action;
control_cache_t cache;
#endif // _di_control_data_t_
/**
+ * Supported payload types.
+ *
+ * error: The payload is an error payload.
+ * controller: The payload is a controller payload.
+ */
+#ifndef _di_control_payload_types_
+ enum {
+ control_payload_type_error_e = 1,
+ control_payload_type_controller_e,
+ };
+#endif // _di_control_payload_types_
+
+/**
+ * The packet payload header data.
+ *
+ * The FSS-000E (Payload) supports multiple objects, but the Control packet does not support this, yet.
+ *
+ * action: The action type code, for any valid action (see: control_action_types enumeration).
+ * type: The packet type represented by the payload packet.
+ * status: The status code represented by the payload packet.
+ * length: The length of the payload content within the payload packet.
+ */
+#ifndef _di_control_payload_header_t_
+ typedef struct {
+ uint8_t action;
+ uint8_t type;
+ f_status_t status;
+ uint16_t length;
+ } control_payload_header_t;
+
+ #define control_payload_header_t_initialize \
+ { \
+ 0, \
+ 0, \
+ f_status_t_initialize, \
+ f_array_length_t_initialize, \
+ }
+#endif // _di_control_payload_header_t_
+
+/**
* Deallocate the control data.
*
* @param data
extern "C" {
#endif
-#ifndef _di_control_command_identify_
- f_status_t control_command_identify(fll_program_data_t * const main, control_data_t * const data, const f_string_static_t command) {
+#ifndef _di_control_action_identify_
+ uint8_t control_action_identify(fll_program_data_t * const main, control_data_t * const data, const f_string_static_t action) {
- if (fl_string_dynamic_compare(command, control_freeze_s) == F_equal_to) {
- data->command = control_command_type_freeze_e;
-
- return F_found;
+ if (fl_string_dynamic_compare(action, control_freeze_s) == F_equal_to) {
+ return control_action_type_freeze_e;
}
- if (fl_string_dynamic_compare(command, control_kill_s) == F_equal_to) {
- data->command = control_command_type_kill_e;
-
- return F_found;
+ if (fl_string_dynamic_compare(action, control_kill_s) == F_equal_to) {
+ return control_action_type_kill_e;
}
- if (fl_string_dynamic_compare(command, control_pause_s) == F_equal_to) {
- data->command = control_command_type_pause_e;
-
- return F_found;
+ if (fl_string_dynamic_compare(action, control_pause_s) == F_equal_to) {
+ return control_action_type_pause_e;
}
- if (fl_string_dynamic_compare(command, control_reboot_s) == F_equal_to) {
- data->command = control_command_type_reboot_e;
-
- return F_found;
+ if (fl_string_dynamic_compare(action, control_reboot_s) == F_equal_to) {
+ return control_action_type_reboot_e;
}
- if (fl_string_dynamic_compare(command, control_reload_s) == F_equal_to) {
- data->command = control_command_type_reload_e;
-
- return F_found;
+ if (fl_string_dynamic_compare(action, control_reload_s) == F_equal_to) {
+ return control_action_type_reload_e;
}
- if (fl_string_dynamic_compare(command, control_rerun_s) == F_equal_to) {
- data->command = control_command_type_rerun_e;
-
- return F_found;
+ if (fl_string_dynamic_compare(action, control_rerun_s) == F_equal_to) {
+ return control_action_type_rerun_e;
}
- if (fl_string_dynamic_compare(command, control_restart_s) == F_equal_to) {
- data->command = control_command_type_restart_e;
-
- return F_found;
+ if (fl_string_dynamic_compare(action, control_restart_s) == F_equal_to) {
+ return control_action_type_restart_e;
}
- if (fl_string_dynamic_compare(command, control_resume_s) == F_equal_to) {
- data->command = control_command_type_resume_e;
-
- return F_found;
+ if (fl_string_dynamic_compare(action, control_resume_s) == F_equal_to) {
+ return control_action_type_resume_e;
}
- if (fl_string_dynamic_compare(command, control_shutdown_s) == F_equal_to) {
- data->command = control_command_type_shutdown_e;
-
- return F_found;
+ if (fl_string_dynamic_compare(action, control_shutdown_s) == F_equal_to) {
+ return control_action_type_shutdown_e;
}
- if (fl_string_dynamic_compare(command, control_start_s) == F_equal_to) {
- data->command = control_command_type_start_e;
-
- return F_found;
+ if (fl_string_dynamic_compare(action, control_start_s) == F_equal_to) {
+ return control_action_type_start_e;
}
- if (fl_string_dynamic_compare(command, control_stop_s) == F_equal_to) {
- data->command = control_command_type_stop_e;
-
- return F_found;
+ if (fl_string_dynamic_compare(action, control_stop_s) == F_equal_to) {
+ return control_action_type_stop_e;
}
- if (fl_string_dynamic_compare(command, control_thaw_s) == F_equal_to) {
- data->command = control_command_type_thaw_e;
-
- return F_found;
+ if (fl_string_dynamic_compare(action, control_thaw_s) == F_equal_to) {
+ return control_action_type_thaw_e;
}
- return F_found_not;
+ return 0;
}
-#endif // _di_control_command_identify_
-
-#ifndef _di_control_command_verify_
- f_status_t control_command_verify(fll_program_data_t * const main, control_data_t * const data) {
-
- switch (data->command) {
- case control_command_type_freeze_e:
- case control_command_type_kill_e:
- case control_command_type_pause_e:
- case control_command_type_reload_e:
- case control_command_type_rerun_e:
- case control_command_type_restart_e:
- case control_command_type_resume_e:
- case control_command_type_start_e:
- case control_command_type_stop_e:
- case control_command_type_thaw_e:
+#endif // _di_control_action_identify_
+
+#ifndef _di_control_action_verify_
+ f_status_t control_action_verify(fll_program_data_t * const main, control_data_t * const data) {
+
+ switch (data->action) {
+ case control_action_type_freeze_e:
+ case control_action_type_kill_e:
+ case control_action_type_pause_e:
+ case control_action_type_reload_e:
+ case control_action_type_rerun_e:
+ case control_action_type_restart_e:
+ case control_action_type_resume_e:
+ case control_action_type_start_e:
+ case control_action_type_stop_e:
+ case control_action_type_thaw_e:
if (main->parameters.remaining.used < 2) {
- control_print_error_parameter_command_rule_not(main, data->argv[main->parameters.remaining.array[0]]);
+ control_print_error_parameter_action_rule_not(main, data->argv[main->parameters.remaining.array[0]]);
return F_status_set_error(F_parameter);
}
else if (main->parameters.remaining.used > 3) {
- control_print_error_parameter_command_rule_too_many(main, data->argv[main->parameters.remaining.array[0]]);
+ control_print_error_parameter_action_rule_too_many(main, data->argv[main->parameters.remaining.array[0]]);
return F_status_set_error(F_parameter);
}
if (!data->argv[main->parameters.remaining.array[1]].used) {
if (main->parameters.remaining.used == 2) {
- control_print_error_parameter_command_rule_empty(main, data->argv[main->parameters.remaining.array[0]]);
+ control_print_error_parameter_action_rule_empty(main, data->argv[main->parameters.remaining.array[0]]);
}
else {
- control_print_error_parameter_command_rule_directory_empty(main, data->argv[main->parameters.remaining.array[0]]);
+ control_print_error_parameter_action_rule_directory_empty(main, data->argv[main->parameters.remaining.array[0]]);
}
return F_status_set_error(F_parameter);
if (main->parameters.remaining.used == 3) {
if (!data->argv[main->parameters.remaining.array[2]].used) {
- control_print_error_parameter_command_rule_basename_empty(main, data->argv[main->parameters.remaining.array[0]]);
+ control_print_error_parameter_action_rule_basename_empty(main, data->argv[main->parameters.remaining.array[0]]);
return F_status_set_error(F_parameter);
}
return F_none;
}
- // @todo the reboot and shutdown need to support date and time commands: "now", "in (a time)", and "at (a time)".
- if (data->command == control_command_type_reboot_e) {
- // @todo (also needs to support kexec calls or kexec needs its own command, which will likely be in the controller program.)
+ // @todo the reboot and shutdown need to support date and time actions: "now", "in (a time)", and "at (a time)".
+ if (data->action == control_action_type_reboot_e) {
+ // @todo (also needs to support kexec calls or kexec needs its own action, which will likely be in the controller program.)
}
- if (data->command == control_command_type_shutdown_e) {
+ if (data->action == control_action_type_shutdown_e) {
// @todo
}
return F_none;
}
-#endif // _di_control_command_verify_
+#endif // _di_control_action_verify_
#ifndef _di_control_packet_build_
f_status_t control_packet_build(fll_program_data_t * const main, control_data_t * const data) {
#endif // _di_control_packet_build_
#ifndef _di_control_packet_receive_
- f_status_t control_packet_receive(fll_program_data_t * const main, control_data_t * const data) {
+ f_status_t control_packet_receive(fll_program_data_t * const main, control_data_t * const data, control_payload_header_t * const header) {
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.header_objects.used = 0;
+ data->cache.header_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;
+
+ header->action = 0;
+ header->type = 0;
+ header->status = F_none;
+ header->length = 0;
f_status_t status = F_none;
- f_array_length_t length = 5;
+ f_array_length_t i = 0;
+ f_string_range_t range_header = f_string_range_t_initialize;
+ f_string_range_t range_payload = f_string_range_t_initialize;
{
+ f_array_length_t length = 5;
uint8_t head[length];
memset(head, 0, sizeof(uint8_t) * length);
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;
+ {
+ f_string_ranges_t *content_header = 0;
+ f_string_ranges_t *content_payload = 0;
+
+ for (; i < data->cache.packet_objects.used; ++i) {
- 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) {
- 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 (content_header) {
+ return F_status_set_error(F_packet_not);
+ }
- // 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);
+ content_header = &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) {
- 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 (content_payload) {
+ return F_status_set_error(F_packet_not);
+ }
- // Only a single "payload" is supported by the FSS-000E (Payload) standard.
- if (range_payload_object) {
- return F_status_set_error(F_packet_not);
+ content_payload = &data->cache.packet_contents.array[i];
}
+ } // for
- range_payload_object = &data->cache.packet_objects.array[i];
- range_payload_content = &data->cache.packet_contents.array[i];
+ if (!content_header || !content_payload) {
+ return F_status_set_error(F_packet_not);
}
- } // for
- if (!range_header_object || !range_payload_object) {
- return F_status_set_error(F_packet_not);
+ range_header = content_header->array[0];
+ range_payload = content_payload->array[0];
}
- // @todo load the "action"s, "length", "status"s, "type"s, and finally the "payload" (if lenth is > 0).
+ {
+ // 0x1 = found action, 0x2 = found length, 0x4 = found status, 0x8 = found_type.
+ uint8_t found = 0;
+ f_number_unsigned_t number = 0;
+ f_string_range_t range = range_header;
+
+ status = fll_fss_basic_list_read(data->cache.large, state, &range, &data->cache.header_objects, &data->cache.header_contents, &data->cache.delimits, 0, 0);
+ if (F_status_is_error(status)) return F_status_set_error(status);
+
+ status = fl_fss_apply_delimit(data->cache.delimits, &data->cache.large);
+ if (F_status_is_error(status)) return status;
+
+ if (!data->cache.header_contents.used) {
+ // @todo if debug print the reason for the failure.
+ return F_status_set_error(F_header);
+ }
+
+ // @todo walk through each range in header_objects, match the first "header" object, get the range from header_contents.array[0], reset the header_objects and header_contents and then pass the retrieved range to the fll_fss_extended_read() function below.
+
+ //status = fll_fss_extended_read(data->cache.large, state, &range, &data->cache.header_objects, &data->cache.header_contents, &data->cache.delimits, 0, 0);
+ if (F_status_is_error(status)) return F_status_set_error(status);
+
+ for (i = 0; i < data->cache.header_objects.used; ++i) {
+
+ if (fl_string_dynamic_partial_compare_string(control_action_s.string, data->cache.large, control_action_s.used, data->cache.header_objects.array[i]) == F_equal_to) {
+ if (!(found & 0x1)) {
+ const f_array_length_t action_length = (data->cache.header_contents.array[i].array[0].stop - data->cache.header_contents.array[i].array[0].start) + 1;
+ char action_string[action_length + 1];
+ const f_string_static_t action = macro_f_string_static_t_initialize(action_string, 0, action_length);
+
+ memcpy(action_string, data->cache.large.string + data->cache.header_contents.array[i].array[0].start, action_length);
+ action_string[action_length] = 0;
+
+ found |= 0x1;
+
+ control_print_debug_packet_header_object_and_content(main, control_action_s, data->cache.large, data->cache.header_contents.array[i].array[0]);
+
+ header->action = control_action_identify(main, data, action);
+
+ if (!header->action) {
+ // @todo if debug print the reason for the failure.
+ return F_status_set_error(F_header);
+ }
+ }
+ else {
+ control_print_warning_packet_header_duplicate_object(main, control_action_s);
+ }
+ }
+ else if (fl_string_dynamic_partial_compare_string(control_length_s.string, data->cache.large, control_length_s.used, data->cache.header_objects.array[i]) == F_equal_to) {
+ if (!(found & 0x2)) {
+ found |= 0x2;
+ number = 0;
+
+ control_print_debug_packet_header_object_and_content(main, control_length_s, data->cache.large, data->cache.header_contents.array[i].array[0]);
+
+ // First attempt to get status as a number.
+ status = fl_conversion_dynamic_partial_to_number_unsigned(data->cache.large, data->cache.header_contents.array[i].array[0], &number);
+
+ if (F_status_is_error(status)) {
+ // @todo if debug print the reason for the failure.
+ return F_status_set_error(F_status);
+ }
+
+ if (number > F_status_size_max_with_bits_d) {
+ // @todo if debug print the reason for the failure.
+ return F_status_set_error(F_status);
+ }
+
+ header->length = (uint16_t) number;
+ }
+ else {
+ control_print_warning_packet_header_duplicate_object(main, control_length_s);
+ }
+ }
+ else if (fl_string_dynamic_partial_compare_string(control_status_s.string, data->cache.large, control_status_s.used, data->cache.header_objects.array[i]) == F_equal_to) {
+ if (!(found & 0x4)) {
+ found |= 0x4;
+ number = 0;
+
+ control_print_debug_packet_header_object_and_content(main, control_status_s, data->cache.large, data->cache.header_contents.array[i].array[0]);
+
+ // First attempt to get status as a number.
+ status = fl_conversion_dynamic_partial_to_number_unsigned(data->cache.large, data->cache.header_contents.array[i].array[0], &number);
+
+ if (F_status_set_fine(status) == F_number) {
+ const f_array_length_t name_length = (data->cache.header_contents.array[i].array[0].stop - data->cache.header_contents.array[i].array[0].start) + 1;
+ char name_string[name_length + 1];
+ const f_string_static_t name = macro_f_string_static_t_initialize(name_string, 0, name_length);
+
+ memcpy(name_string, data->cache.large.string + data->cache.header_contents.array[i].array[0].start, name_length);
+ name_string[name_length] = 0;
+
+ status = fll_status_string_from(name, &header->status);
+
+ if (F_status_is_error(status)) {
+ // @todo if debug print the reason for the failure.
+ return status;
+ }
+ }
+ else if (F_status_is_error(status)) {
+ // @todo if debug print the reason for the failure.
+ return F_status_set_error(F_status);
+ }
+ }
+ else {
+ control_print_warning_packet_header_duplicate_object(main, control_length_s);
+ }
+ }
+ else if (fl_string_dynamic_partial_compare_string(control_type_s.string, data->cache.large, control_type_s.used, data->cache.header_objects.array[i]) == F_equal_to) {
+ if (!(found & 0x8)) {
+ found |= 0x8;
+
+ control_print_debug_packet_header_object_and_content(main, control_type_s, data->cache.large, data->cache.header_contents.array[i].array[0]);
+
+ if (fl_string_dynamic_partial_compare_string(control_controller_s.string, data->cache.large, control_controller_s.used, data->cache.header_contents.array[i].array[0]) == F_equal_to) {
+ header->type = control_payload_type_controller_e;
+ }
+ else if (fl_string_dynamic_partial_compare_string(control_error_s.string, data->cache.large, control_error_s.used, data->cache.header_contents.array[i].array[0]) == F_equal_to) {
+ header->type = control_payload_type_error_e;
+ }
+ else {
+ // @todo if debug print the reason for the failure.
+ return F_status_set_error(F_header);
+ }
+ }
+ else {
+ control_print_warning_packet_header_duplicate_object(main, control_type_s);
+ }
+ }
+ }
+ }
- //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 based on header->type, handle the data. if type is control_payload_type_error_e, then check the header->length and conditionally get the message from the payload content.
+ // @todo this handling may likely be moved outside of this function.
}
// @todo
/**
- * Identify the command code the given name represents.
+ * Identify the action code the given name represents.
*
* @param main
* The main program data.
* @param data
* The control data.
- * @param command
- * The parameter representing a command.
+ * @param action
+ * The parameter representing a action.
*
* @return
- * F_found on success.
- * F_found_not if name is unknown.
+ * action type code on success.
+ * 0 if name is unknown.
*/
-#ifndef _di_control_command_identify_
- extern f_status_t control_command_identify(fll_program_data_t * const main, control_data_t * const data, const f_string_static_t command) F_attribute_visibility_internal_d;
-#endif // _di_control_command_identify_
+#ifndef _di_control_action_identify_
+ extern uint8_t control_action_identify(fll_program_data_t * const main, control_data_t * const data, const f_string_static_t action) F_attribute_visibility_internal_d;
+#endif // _di_control_action_identify_
/**
- * Verify that the additional parameters are reasonably correct for the identified command.
+ * Verify that the additional parameters are reasonably correct for the identified action.
*
* @param main
* The main program data.
* @param data
* The control data.
*/
-#ifndef _di_control_command_verify_
- extern f_status_t control_command_verify(fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d;
-#endif // _di_control_command_verify_
+#ifndef _di_control_action_verify_
+ extern f_status_t control_action_verify(fll_program_data_t * const main, control_data_t * const data) F_attribute_visibility_internal_d;
+#endif // _di_control_action_verify_
/**
* Build the payload, storing it in the large cache.
/**
* Receive the response from the remote socket, storing it in the large cache.
*
+ * @todo consider returning F_header (with error bit) fo most header processing errors rather than individual status codes.
+ *
* @param main
* The main program data.
* @param data
* The control data.
+ * @param header
+ * The control payload packet header data.
*
* @return
* F_none on success.
*
+ * F_header (with error bit) If there is a problem processing the packet header.
* 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.
* @see fll_fss_extended_read()
*/
#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;
+ extern f_status_t control_packet_receive(fll_program_data_t * const main, control_data_t * const data, control_payload_header_t * const header) F_attribute_visibility_internal_d;
#endif // _di_control_packet_receive_
/**
extern "C" {
#endif
-#ifndef _di_control_print_error_parameter_commands_none_
- void control_print_error_parameter_commands_none(fll_program_data_t * const main) {
+#ifndef _di_control_print_debug_packet_header_object_and_content_
+ void control_print_debug_packet_header_object_and_content(fll_program_data_t * const main, const f_string_static_t object, const f_string_static_t content, const f_string_range_t range_content) {
+
+ if (main->output.verbosity == f_console_verbosity_debug_e) return;
+
+ flockfile(main->error.to.stream);
+
+ fl_print_format("%rPacket header Object '%[%Q%]", main->output.to.stream, f_string_eol_s, main->context.set.notable, object, main->context.set.notable);
+ fl_print_format("' has value '%[%/Q%]'.%r", main->output.to.stream, main->context.set.notable, content, range_content, main->context.set.notable, f_string_eol_s);
+
+ funlockfile(main->error.to.stream);
+ }
+#endif // _di_control_print_debug_packet_header_object_and_content_
+
+#ifndef _di_control_print_error_parameter_actions_none_
+ void control_print_error_parameter_actions_none(fll_program_data_t * const main) {
if (main->error.verbosity == f_console_verbosity_quiet_e) return;
- fll_print_format("%r%[%QNo commands provided.%]%r", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error, f_string_eol_s);
+ fll_print_format("%r%[%QNo actions provided.%]%r", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error, f_string_eol_s);
}
-#endif // _di_control_print_error_parameter_commands_none_
+#endif // _di_control_print_error_parameter_actions_none_
-#ifndef _di_control_print_error_parameter_command_not_
- void control_print_error_parameter_command_not(fll_program_data_t * const main, const f_string_static_t command) {
+#ifndef _di_control_print_error_parameter_action_not_
+ void control_print_error_parameter_action_not(fll_program_data_t * const main, const f_string_static_t action) {
if (main->error.verbosity == f_console_verbosity_quiet_e) return;
flockfile(main->error.to.stream);
fl_print_format("%r%[%QThe parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
- fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, command, main->context.set.notable);
- fl_print_format("%[' is not a known controller command.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s);
+ fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, action, main->context.set.notable);
+ fl_print_format("%[' is not a known controller action.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s);
funlockfile(main->error.to.stream);
}
-#endif // _di_control_print_error_parameter_command_not_
+#endif // _di_control_print_error_parameter_action_not_
-#ifndef _di_control_print_error_parameter_command_rule_basename_empty_
- void control_print_error_parameter_command_rule_basename_empty(fll_program_data_t * const main, const f_string_static_t command) {
+#ifndef _di_control_print_error_parameter_action_rule_basename_empty_
+ void control_print_error_parameter_action_rule_basename_empty(fll_program_data_t * const main, const f_string_static_t action) {
if (main->error.verbosity == f_console_verbosity_quiet_e) return;
flockfile(main->error.to.stream);
- fl_print_format("%r%[%QThe command parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
- fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, command, main->context.set.notable);
+ fl_print_format("%r%[%QThe action parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
+ fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, action, main->context.set.notable);
fl_print_format("%[' a rule base name cannot be an empty string.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s);
funlockfile(main->error.to.stream);
}
-#endif // _di_control_print_error_parameter_command_rule_basename_empty_
+#endif // _di_control_print_error_parameter_action_rule_basename_empty_
-#ifndef _di_control_print_error_parameter_command_rule_directory_empty_
- void control_print_error_parameter_command_rule_directory_empty(fll_program_data_t * const main, const f_string_static_t command) {
+#ifndef _di_control_print_error_parameter_action_rule_directory_empty_
+ void control_print_error_parameter_action_rule_directory_empty(fll_program_data_t * const main, const f_string_static_t action) {
if (main->error.verbosity == f_console_verbosity_quiet_e) return;
flockfile(main->error.to.stream);
- fl_print_format("%r%[%QThe command parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
- fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, command, main->context.set.notable);
+ fl_print_format("%r%[%QThe action parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
+ fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, action, main->context.set.notable);
fl_print_format("%[' a rule directory path cannot be an empty string.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s);
funlockfile(main->error.to.stream);
}
-#endif // _di_control_print_error_parameter_command_rule_directory_empty_
+#endif // _di_control_print_error_parameter_action_rule_directory_empty_
-#ifndef _di_control_print_error_parameter_command_rule_empty_
- void control_print_error_parameter_command_rule_empty(fll_program_data_t * const main, const f_string_static_t command) {
+#ifndef _di_control_print_error_parameter_action_rule_empty_
+ void control_print_error_parameter_action_rule_empty(fll_program_data_t * const main, const f_string_static_t action) {
if (main->error.verbosity == f_console_verbosity_quiet_e) return;
flockfile(main->error.to.stream);
- fl_print_format("%r%[%QThe command parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
- fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, command, main->context.set.notable);
+ fl_print_format("%r%[%QThe action parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
+ fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, action, main->context.set.notable);
fl_print_format("%[' a rule name cannot be an empty string.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s);
funlockfile(main->error.to.stream);
}
-#endif // _di_control_print_error_parameter_command_rule_empty_
+#endif // _di_control_print_error_parameter_action_rule_empty_
-#ifndef _di_control_print_error_parameter_command_rule_not_
- void control_print_error_parameter_command_rule_not(fll_program_data_t * const main, const f_string_static_t command) {
+#ifndef _di_control_print_error_parameter_action_rule_not_
+ void control_print_error_parameter_action_rule_not(fll_program_data_t * const main, const f_string_static_t action) {
if (main->error.verbosity == f_console_verbosity_quiet_e) return;
flockfile(main->error.to.stream);
- fl_print_format("%r%[%QThe command parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
- fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, command, main->context.set.notable);
+ fl_print_format("%r%[%QThe action parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
+ fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, action, main->context.set.notable);
fl_print_format("%[' requires either a full rule name or a rule directory path along with the rule base name.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s);
funlockfile(main->error.to.stream);
}
-#endif // _di_control_print_error_parameter_command_rule_not_
+#endif // _di_control_print_error_parameter_action_rule_not_
-#ifndef _di_control_print_error_parameter_command_rule_too_many_
- void control_print_error_parameter_command_rule_too_many(fll_program_data_t * const main, const f_string_static_t command) {
+#ifndef _di_control_print_error_parameter_action_rule_too_many_
+ void control_print_error_parameter_action_rule_too_many(fll_program_data_t * const main, const f_string_static_t action) {
if (main->error.verbosity == f_console_verbosity_quiet_e) return;
flockfile(main->error.to.stream);
- fl_print_format("%r%[%QThe command parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
- fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, command, main->context.set.notable);
+ fl_print_format("%r%[%QThe action parameter '%]", main->error.to.stream, f_string_eol_s, main->context.set.error, main->error.prefix, main->context.set.error);
+ fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, action, main->context.set.notable);
fl_print_format("%[' has too many arguments.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s);
funlockfile(main->error.to.stream);
}
-#endif // _di_control_print_error_parameter_command_rule_too_many_
+#endif // _di_control_print_error_parameter_action_rule_too_many_
#ifndef _di_control_print_error_parameter_value_empty_
void control_print_error_parameter_value_empty(fll_program_data_t * const main, const f_string_static_t parameter) {
}
#endif // _di_control_print_signal_received_
+#ifndef _di_control_print_warning_packet_header_duplicate_object_
+ void control_print_warning_packet_header_duplicate_object(fll_program_data_t * const main, const f_string_static_t response_header) {
+
+ if (main->warning.verbosity == f_console_verbosity_debug_e) return;
+
+ flockfile(main->warning.to.stream);
+
+ fl_print_format("%r%[%QThe received response header '%]", main->warning.to.stream, f_string_eol_s, main->context.set.warning, main->warning.prefix, main->context.set.warning);
+ fl_print_format("%[%Q%]", main->warning.to.stream, main->context.set.notable, response_header, main->context.set.notable);
+ fl_print_format("%[' is repeated.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s);
+
+ funlockfile(main->warning.to.stream);
+ }
+#endif // _di_control_print_warning_packet_header_duplicate_object_
+
#ifdef __cplusplus
} // extern "C"
#endif
#endif
/**
- * Print an error message about no commands being provided.
+ * Print a message displaying the object and content for some packet header.
*
* @param main
* The main program data.
+ * @param object
+ * The object string.
+ * @param content
+ * The content string.
+ * @param range_content
+ * The range representing the content where the content is found within the content string.
*/
-#ifndef _di_control_print_error_parameter_commands_none_
- extern void control_print_error_parameter_commands_none(fll_program_data_t * const main) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_parameter_commands_none_
+#ifndef _di_control_print_debug_packet_header_object_and_content_
+ extern void control_print_debug_packet_header_object_and_content(fll_program_data_t * const main, const f_string_static_t object, const f_string_static_t content, const f_string_range_t range_content) F_attribute_visibility_internal_d;
+#endif // _di_control_print_debug_packet_header_object_and_content_
/**
- * Print an error message about the given parameter not matching the known set of controller commands.
+ * Print an error message about no actions being provided.
*
* @param main
* The main program data.
- * @param command
- * The parameter representing a command.
*/
-#ifndef _di_control_print_error_parameter_command_not_
- extern void control_print_error_parameter_command_not(fll_program_data_t * const main, const f_string_static_t command) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_parameter_command_not_
+#ifndef _di_control_print_error_parameter_actions_none_
+ extern void control_print_error_parameter_actions_none(fll_program_data_t * const main) F_attribute_visibility_internal_d;
+#endif // _di_control_print_error_parameter_actions_none_
/**
- * Print an error message about the given parameter being a rule command having an empty rule basename.
+ * Print an error message about the given parameter not matching the known set of controller actions.
*
* @param main
* The main program data.
- * @param command
- * The parameter representing a command.
+ * @param action
+ * The parameter representing a action.
*/
-#ifndef _di_control_print_error_parameter_command_rule_basename_empty_
- extern void control_print_error_parameter_command_rule_basename_empty(fll_program_data_t * const main, const f_string_static_t command) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_parameter_command_rule_basename_empty_
+#ifndef _di_control_print_error_parameter_action_not_
+ extern void control_print_error_parameter_action_not(fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d;
+#endif // _di_control_print_error_parameter_action_not_
/**
- * Print an error message about the given parameter being a rule command having an empty rule directory path.
+ * Print an error message about the given parameter being a rule action having an empty rule basename.
*
* @param main
* The main program data.
- * @param command
- * The parameter representing a command.
+ * @param action
+ * The parameter representing a action.
*/
-#ifndef _di_control_print_error_parameter_command_rule_directory_empty_
- extern void control_print_error_parameter_command_rule_directory_empty(fll_program_data_t * const main, const f_string_static_t command) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_parameter_command_rule_directory_empty_
+#ifndef _di_control_print_error_parameter_action_rule_basename_empty_
+ extern void control_print_error_parameter_action_rule_basename_empty(fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d;
+#endif // _di_control_print_error_parameter_action_rule_basename_empty_
/**
- * Print an error message about the given parameter being a rule command having an empty rule name.
+ * Print an error message about the given parameter being a rule action having an empty rule directory path.
*
* @param main
* The main program data.
- * @param command
- * The parameter representing a command.
+ * @param action
+ * The parameter representing a action.
*/
-#ifndef _di_control_print_error_parameter_command_rule_empty_
- extern void control_print_error_parameter_command_rule_empty(fll_program_data_t * const main, const f_string_static_t command) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_parameter_command_rule_empty_
+#ifndef _di_control_print_error_parameter_action_rule_directory_empty_
+ extern void control_print_error_parameter_action_rule_directory_empty(fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d;
+#endif // _di_control_print_error_parameter_action_rule_directory_empty_
/**
- * Print an error message about the given parameter being a rule command but no rule name is specified.
+ * Print an error message about the given parameter being a rule action having an empty rule name.
*
* @param main
* The main program data.
- * @param command
- * The parameter representing a command.
+ * @param action
+ * The parameter representing a action.
*/
-#ifndef _di_control_print_error_parameter_command_rule_not_
- extern void control_print_error_parameter_command_rule_not(fll_program_data_t * const main, const f_string_static_t command) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_parameter_command_rule_not_
+#ifndef _di_control_print_error_parameter_action_rule_empty_
+ extern void control_print_error_parameter_action_rule_empty(fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d;
+#endif // _di_control_print_error_parameter_action_rule_empty_
/**
- * Print an error message about the given parameter being a rule command having too many arguments passed.
+ * Print an error message about the given parameter being a rule action but no rule name is specified.
*
* @param main
* The main program data.
- * @param command
- * The parameter representing a command.
+ * @param action
+ * The parameter representing a action.
*/
-#ifndef _di_control_print_error_parameter_command_rule_too_many_
- extern void control_print_error_parameter_command_rule_too_many(fll_program_data_t * const main, const f_string_static_t command) F_attribute_visibility_internal_d;
-#endif // _di_control_print_error_parameter_command_rule_too_many_
+#ifndef _di_control_print_error_parameter_action_rule_not_
+ extern void control_print_error_parameter_action_rule_not(fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d;
+#endif // _di_control_print_error_parameter_action_rule_not_
+
+/**
+ * Print an error message about the given parameter being a rule action having too many arguments passed.
+ *
+ * @param main
+ * The main program data.
+ * @param action
+ * The parameter representing a action.
+ */
+#ifndef _di_control_print_error_parameter_action_rule_too_many_
+ extern void control_print_error_parameter_action_rule_too_many(fll_program_data_t * const main, const f_string_static_t action) F_attribute_visibility_internal_d;
+#endif // _di_control_print_error_parameter_action_rule_too_many_
/**
* Print an error message about the parameter's associated value being an empty string.
extern void control_print_signal_received(fll_program_data_t * const main, const f_status_t signal) F_attribute_visibility_internal_d;
#endif // _di_control_print_signal_received_
+/**
+ * Print a warning message about a response header being repeated (when debugging).
+ *
+ * This program currently does not support multiple headers for any given valid header Object.
+ *
+ * @param main
+ * The main program data.
+ * @param response_header
+ * The repeated response header.
+ */
+#ifndef _di_control_print_warning_packet_header_duplicate_object_
+ extern void control_print_warning_packet_header_duplicate_object(fll_program_data_t * const main, const f_string_static_t response_header) F_attribute_visibility_internal_d;
+#endif // _di_control_print_warning_packet_header_duplicate_object_
+
#ifdef __cplusplus
} // extern "C"
#endif
f_print
f_signal
f_socket
+f_status_string
fl_fss
fl_print
fl_string
fll_fss
fll_print
fll_program
+fll_status_string
build_indexer_arguments rcs
build_language c
build_libraries -lc
-build_libraries-individual -lfll_error -lfll_fss -lfll_print -lfll_program -lfl_conversion -lfl_fss -lfl_print -lfl_string -lf_color -lf_console -lf_conversion -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_socket -lf_status_string -lf_string -lf_type_array -lf_utf
+build_libraries-individual -lfll_error -lfll_fss -lfll_print -lfll_program -lfll_status_string -lfl_conversion -lfl_fss -lfl_print -lfl_string -lf_color -lf_console -lf_conversion -lf_file -lf_fss -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_socket -lf_status_string -lf_string -lf_type_array -lf_utf
build_libraries-level -lfll_2 -lfll_1 -lfll_0
build_libraries-monolithic -lfll
build_libraries_shared
#include <fll/level_0/print.h>
#include <fll/level_0/signal.h>
#include <fll/level_0/socket.h>
+#include <fll/level_0/status_string.h>
// FLL-1 includes.
#include <fll/level_1/control_group.h>
#include <fll/level_2/path.h>
#include <fll/level_2/print.h>
#include <fll/level_2/program.h>
+#include <fll/level_2/status_string.h>
// Controller includes.
#include <program/controller/common.h>
*
* @return
* F_none on success.
- * F_status if main thread is disabled and write lock was never achieved.
*
* F_interrupt (with error bit set) on (exit) signal received, lock will not be set when this is returned.
*
*
* @return
* F_none on success.
- * F_status if main thread is disabled and write lock was never achieved.
*
* F_interrupt (with error bit set) on (exit) signal received, lock will not be set when this is returned.
*
f_print
f_signal
f_socket
+f_status_string
f_thread
fl_control_group
fl_conversion
fll_path
fll_print
fll_program
+fll_status_string
build_indexer_arguments rcs
build_language c
build_libraries -lc -lcap
-build_libraries-individual -lfll_control_group -lfll_error -lfll_execute -lfll_fss -lfll_path -lfll_print -lfll_program
+build_libraries-individual -lfll_control_group -lfll_error -lfll_execute -lfll_fss -lfll_path -lfll_print -lfll_program -lfll_status_string
build_libraries-individual -lfl_control_group -lfl_conversion -lfl_directory -lfl_environment -lfl_fss -lfl_iki -lfl_print -lfl_string
build_libraries-individual -lf_account -lf_capability -lf_color -lf_console -lf_control_group -lf_conversion -lf_directory -lf_environment -lf_execute -lf_file -lf_fss -lf_iki -lf_limit -lf_memory -lf_path -lf_pipe -lf_print -lf_signal -lf_socket -lf_status_string -lf_string -lf_thread -lf_type_array -lf_utf
build_libraries-level -lfll_2 -lfll_1 -lfll_0