#include "control.h"
+#include "private-common.h"
#ifdef __cplusplus
extern "C" {
#ifndef _di_control_parameters_
const f_string_static_t control_short_name_s = macro_f_string_static_t_initialize(CONTROL_short_name_s, 0, CONTROL_short_name_s_length);
+ const f_string_static_t control_short_return_s = macro_f_string_static_t_initialize(CONTROL_short_return_s, 0, CONTROL_short_return_s_length);
const f_string_static_t control_short_settings_s = macro_f_string_static_t_initialize(CONTROL_short_settings_s, 0, CONTROL_short_settings_s_length);
const f_string_static_t control_short_socket_s = macro_f_string_static_t_initialize(CONTROL_short_socket_s, 0, CONTROL_short_socket_s_length);
const f_string_static_t control_long_name_s = macro_f_string_static_t_initialize(CONTROL_long_name_s, 0, CONTROL_long_name_s_length);
+ const f_string_static_t control_long_return_s = macro_f_string_static_t_initialize(CONTROL_long_return_s, 0, CONTROL_long_return_s_length);
const f_string_static_t control_long_settings_s = macro_f_string_static_t_initialize(CONTROL_long_settings_s, 0, CONTROL_long_settings_s_length);
const f_string_static_t control_long_socket_s = macro_f_string_static_t_initialize(CONTROL_long_socket_s, 0, CONTROL_long_socket_s_length);
#endif // _di_control_parameters_
+#ifndef _di_control_action_type_name_
+ f_string_static_t control_action_type_name(const uint8_t type) {
+
+ switch (type) {
+ case control_action_type_freeze_e:
+ return control_freeze_s;
+
+ case control_action_type_kill_e:
+ return control_kill_s;
+
+ case control_action_type_pause_e:
+ return control_pause_s;
+
+ case control_action_type_reboot_e:
+ return control_reboot_s;
+
+ case control_action_type_reload_e:
+ return control_reload_s;
+
+ case control_action_type_rerun_e:
+ return control_rerun_s;
+
+ case control_action_type_restart_e:
+ return control_restart_s;
+
+ case control_action_type_resume_e:
+ return control_resume_s;
+
+ case control_action_type_shutdown_e:
+ return control_shutdown_s;
+
+ case control_action_type_start_e:
+ return control_start_s;
+
+ case control_action_type_stop_e:
+ return control_stop_s;
+
+ case control_action_type_thaw_e:
+ return control_thaw_s;
+ }
+
+ return f_string_empty_s;
+ }
+#endif // _di_control_action_type_name_
+
+#ifndef _di_control_payload_type_name_
+ f_string_static_t control_payload_type_name(const uint8_t type) {
+
+ switch (type) {
+ case control_payload_type_controller_e:
+ return control_controller_s;
+
+ case control_payload_type_error_e:
+ return control_error_s;
+ }
+
+ return f_string_empty_s;
+ }
+#endif // _di_control_payload_type_name_
+
#ifndef _di_control_main_delete_
f_status_t control_main_delete(fll_program_data_t * const main) {
*/
#ifndef _di_control_parameters_
#define CONTROL_short_name_s "n"
+ #define CONTROL_short_return_s "R"
#define CONTROL_short_settings_s "s"
#define CONTROL_short_socket_s "k"
#define CONTROL_long_name_s "name"
+ #define CONTROL_long_return_s "return"
#define CONTROL_long_settings_s "settings"
#define CONTROL_long_socket_s "socket"
#define CONTROL_short_name_s_length 1
+ #define CONTROL_short_return_s_length 1
#define CONTROL_short_settings_s_length 1
#define CONTROL_short_socket_s_length 1
#define CONTROL_long_name_s_length 4
+ #define CONTROL_long_return_s_length 6
#define CONTROL_long_settings_s_length 8
#define CONTROL_long_socket_s_length 6
extern const f_string_static_t control_short_name_s;
+ extern const f_string_static_t control_short_return_s;
extern const f_string_static_t control_short_settings_s;
extern const f_string_static_t control_short_socket_s;
extern const f_string_static_t control_long_name_s;
+ extern const f_string_static_t control_long_return_s;
extern const f_string_static_t control_long_settings_s;
extern const f_string_static_t control_long_socket_s;
control_parameter_version_e,
control_parameter_name_e,
+ control_parameter_return_e,
control_parameter_settings_e,
control_parameter_socket_e,
};
macro_f_console_parameter_t_initialize(f_console_standard_short_debug_s.string, f_console_standard_long_debug_s.string, 0, 0, f_console_type_inverse_e), \
macro_f_console_parameter_t_initialize(f_console_standard_short_version_s.string, f_console_standard_long_version_s.string, 0, 0, f_console_type_inverse_e), \
macro_f_console_parameter_t_initialize(control_short_name_s.string, control_long_name_s.string, 0, 1, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(control_short_return_s.string, control_long_return_s.string, 0, 1, f_console_type_normal_e), \
macro_f_console_parameter_t_initialize(control_short_settings_s.string, control_long_settings_s.string, 0, 1, f_console_type_normal_e), \
macro_f_console_parameter_t_initialize(control_short_socket_s.string, control_long_socket_s.string, 0, 1, f_console_type_normal_e), \
}
- #define control_total_parameters_d 12
+ #define control_total_parameters_d 13
#endif // _di_control_parameters_
/**
+ * Get the name of the action type.
+ *
+ * @param type
+ * The action type id.
+ *
+ * @return
+ * The string associated with the action type.
+ */
+#ifndef _di_control_action_type_name_
+ extern f_string_static_t control_action_type_name(const uint8_t type);
+#endif // _di_control_action_type_name_
+
+/**
+ * Get the name of the payload type.
+ *
+ * @param type
+ * The payload type id.
+ *
+ * @return
+ * The string associated with the payload type.
+ */
+#ifndef _di_control_payload_type_name_
+ extern f_string_static_t control_payload_type_name(const uint8_t type);
+#endif // _di_control_payload_type_name_
+
+/**
* Deallocate main.
*
* Be sure to call this after executing control_main().
f_print_dynamic_raw(f_string_eol_s, main->output.to.stream);
fll_program_print_help_option(main->output.to, main->context, control_short_name_s, control_long_name_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify the name of the controller socket file.");
+ fll_program_print_help_option(main->output.to, main->context, control_short_return_s, control_long_return_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print a message about the response 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.");
fl_print_format(" as a single parameter or two parameters with the first representing the rule directory path '%[boot%]'", main->output.to.stream, main->context.set.notable, main->context.set.notable);
fl_print_format(" and the second representing the rule base name '%[root%]'.%r%r", main->output.to.stream, main->context.set.notable, main->context.set.notable, f_string_eol_s, f_string_eol_s);
+ fl_print_format(" The %[%r%r%] parameter is intended to be used for scripting and is of the form \"response [type] [action] [status]\".%r", main->output.to.stream, main->context.set.notable, f_console_symbol_long_enable_s, control_long_return_s, main->context.set.notable, f_string_eol_s);
+ fl_print_format(" Be sure to use the %[%r%r%] parameter to suppress output when using this in scripting.%r", main->output.to.stream, main->context.set.notable, f_console_symbol_long_disable_s, f_console_standard_long_quiet_s, main->context.set.notable, f_string_eol_s);
+ fl_print_format(" No response is returned on program errors, especially those errors that prevent communicating to the controller.%r%r", main->output.to.stream, f_string_eol_s, f_string_eol_s);
+
fflush(main->output.to.stream);
funlockfile(main->output.to.stream);
}
}
else {
- status = control_packet_process(main, &data, header);
+ status = control_packet_process(main, &data, &header);
+ // Print the error message only if the error message is not already printed.
if (F_status_is_error(status)) {
- fll_error_print(main->error, F_status_set_fine(status), "control_packet_process", F_true);
+ if (header.type != control_payload_type_error_e && (header.type != control_payload_type_controller_e || F_status_set_fine(status) != header.status || (header.status != F_failure && header.status != F_busy))) {
+ fll_error_print(main->error, F_status_set_fine(status), "control_packet_process", F_true);
+ }
}
}
}
}
#endif // _di_control_action_identify_
-#ifndef _di_control_action_type_name_
- f_string_static_t control_action_type_name(const uint8_t type) {
-
- switch (type) {
- case control_action_type_freeze_e:
- return control_freeze_s;
-
- case control_action_type_kill_e:
- return control_kill_s;
-
- case control_action_type_pause_e:
- return control_pause_s;
-
- case control_action_type_reboot_e:
- return control_reboot_s;
-
- case control_action_type_reload_e:
- return control_reload_s;
-
- case control_action_type_rerun_e:
- return control_rerun_s;
-
- case control_action_type_restart_e:
- return control_restart_s;
-
- case control_action_type_resume_e:
- return control_resume_s;
-
- case control_action_type_shutdown_e:
- return control_shutdown_s;
-
- case control_action_type_start_e:
- return control_start_s;
-
- case control_action_type_stop_e:
- return control_stop_s;
-
- case control_action_type_thaw_e:
- return control_thaw_s;
- }
-
- return f_string_empty_s;
- }
-#endif // _di_control_action_type_name_
-
#ifndef _di_control_action_verify_
f_status_t control_action_verify(fll_program_data_t * const main, control_data_t * const data) {
#endif // _di_control_packet_receive_
#ifndef _di_control_packet_process_
- f_status_t control_packet_process(fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header) {
+ f_status_t control_packet_process(fll_program_data_t * const main, control_data_t * const data, control_payload_header_t * const header) {
+
+ f_string_static_t string_status = f_string_static_t_initialize;
+
+ {
+ const f_status_t status = f_status_string_to(header->status, &string_status);
+
+ if (F_status_is_error(status)) {
+ control_print_warning_packet_process_string_to_failed(main, header->status, status);
+ }
+ }
+
+ if (main->parameters.array[control_parameter_return_e].result == f_console_result_found_e) {
+ fll_print_format("%rresponse %q %q %q%r", main->output.to.stream, f_string_eol_s, control_payload_type_name(header->type), control_action_type_name(header->action), string_status, f_string_eol_s);
+ }
+ else if (header->type == control_payload_type_error_e) {
+ control_print_error_packet_response(main, data, *header, string_status);
+ }
+ else if (header->status == F_failure || header->status == F_busy || header->status == F_done || header->status == F_success) {
+ control_print_controller_packet_response(main, data, *header, string_status);
+ }
+ else {
- if (header.type == control_payload_type_error_e) {
- control_print_error_packet_response(main, data, header);
+ // Set type to 0 to inform the caller to handle this error.
+ header->type = 0;
- return F_none;
+ return F_status_set_error(F_known_not);
}
- // @todo based on header->type, handle the data.
+ if (header->type == control_payload_type_error_e || header->status == F_failure || header->status == F_busy) {
+ return F_status_set_error(header->status);
+ }
- return F_none;
+ return header->status;
}
#endif // _di_control_packet_process_
#endif // _di_control_action_identify_
/**
- * Get the name of the action type.
- *
- * @param type
- * The action type id.
- *
- * @return
- * The string associated with the action type.
- */
-#ifndef _di_control_action_type_name_
- extern f_string_static_t control_action_type_name(const uint8_t type) F_attribute_visibility_internal_d;
-#endif // _di_control_action_type_name_
-
-/**
* Verify that the additional parameters are reasonably correct for the identified action.
*
* @param main
* The control data.
* @param header
* The control payload packet header data.
+ *
+ * @return
+ * F_done on success but action has no success or failure states.
+ * F_success on success.
+ *
+ * F_busy (with error bit)
+ * F_failure (with error bit) on success but controller returned failure for action.
+ * Any error (with error bit) on failure where the error is defined by the controller service.
*/
#ifndef _di_control_packet_process_
- extern f_status_t control_packet_process(fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header) F_attribute_visibility_internal_d;
+ extern f_status_t control_packet_process(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_process_
/**
extern "C" {
#endif
+#ifndef _di_control_print_controller_packet_response_
+ void control_print_controller_packet_response(fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header, const f_string_static_t string_status) {
+
+ if (header.status == F_failure) {
+ if (main->error.verbosity == f_console_verbosity_quiet_e) return;
+
+ flockfile(main->error.to.stream);
+
+ fl_print_format("%r%[%QThe action '%]", 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, control_action_type_name(header.action), main->context.set.notable);
+ fl_print_format("%[' failed with status '%]", main->error.to.stream, main->context.set.error, main->context.set.error);
+ fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, string_status, main->context.set.notable);
+ fl_print_format("%[' (%]", main->error.to.stream, main->context.set.error, main->context.set.error);
+ fl_print_format("%[%ui%]", main->error.to.stream, main->context.set.notable, header.status, main->context.set.notable);
+
+ if (header.length) {
+ fl_print_format("%[): %/Q%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, data->cache.large, data->cache.packet_contents.array[data->cache.packet_contents.used - 1].array[0], f_string_eol_s);
+ }
+ else {
+ fl_print_format("%[).%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s);
+ }
+
+ funlockfile(main->error.to.stream);
+
+ return;
+ }
+
+ if (header.status == F_busy) {
+ if (main->warning.verbosity == f_console_verbosity_quiet_e) return;
+
+ flockfile(main->warning.to.stream);
+
+ fl_print_format("%r%[%QThe action '%]", 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, control_action_type_name(header.action), main->context.set.notable);
+ fl_print_format("%[' could not be performed because the service is busy.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s);
+
+ funlockfile(main->warning.to.stream);
+
+ return;
+ }
+
+ if (main->output.verbosity == f_console_verbosity_quiet_e) return;
+
+ flockfile(main->output.to.stream);
+
+ fl_print_format("%rThe action '", main->output.to.stream, f_string_eol_s);
+ fl_print_format("%[%q%]", main->output.to.stream, main->context.set.notable, control_action_type_name(header.action), main->context.set.notable);
+
+ if (header.status == F_done) {
+ fl_print_format("' is performed", main->output.to.stream);
+ }
+ else {
+ fl_print_format("' is successfully performed", main->output.to.stream);
+ }
+
+ if (header.length) {
+ fl_print_format(": %/Q%r", main->output.to.stream, data->cache.large, data->cache.packet_contents.array[data->cache.packet_contents.used - 1].array[0], f_string_eol_s);
+ }
+ else {
+ fl_print_format(".%r", main->output.to.stream, f_string_eol_s);
+ }
+
+ funlockfile(main->output.to.stream);
+ }
+#endif // _di_control_print_controller_packet_response_
+
#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 content_range) {
#endif // _di_control_print_debug_packet_message_
#ifndef _di_control_print_error_packet_response_
- void control_print_error_packet_response(fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header) {
+ void control_print_error_packet_response(fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header, const f_string_static_t string_status) {
if (main->error.verbosity == f_console_verbosity_quiet_e) return;
flockfile(main->error.to.stream);
fl_print_format("%r%[%QReceived error response for " CONTROL_action_s " '%]", 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, control_action_type_name(header.action), main->context.set.notable);
- fl_print_format("%[' (with status %[", 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, control_action_type_name(header.action), main->context.set.notable);
+ fl_print_format("%[' with status '%]", main->error.to.stream, main->context.set.error, main->context.set.error);
+ fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, string_status, main->context.set.notable);
+ fl_print_format("%[' (%]", main->error.to.stream, main->context.set.error, main->context.set.error);
fl_print_format("%[%ui%]", main->error.to.stream, main->context.set.notable, header.status, main->context.set.notable);
if (header.length) {
- fl_print_format("%[): %/Q%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, data->cache.large, data->cache.header_contents.array[0].array[0], f_string_eol_s);
+ fl_print_format("%[): %/Q%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, data->cache.large, data->cache.packet_contents.array[data->cache.packet_contents.used - 1].array[0], f_string_eol_s);
}
else {
fl_print_format("%[).%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s);
flockfile(main->warning.to.stream);
- fl_print_format("%]%r%r%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s, f_string_eol_s, main->context.set.warning, main->context.set.warning);
+ fl_print_format("%]%r%r%[Received signal code%] ", main->warning.to.stream, main->context.set.reset, f_string_eol_s, f_string_eol_s, main->context.set.warning, main->context.set.warning);
fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable);
fl_print_format("%[.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s);
}
#endif // _di_control_print_warning_packet_header_duplicate_object_
+#ifndef _di_control_print_warning_packet_process_string_to_failed_
+ void control_print_warning_packet_process_string_to_failed(fll_program_data_t * const main, const f_status_t status_of, const f_status_t status_error) {
+
+ if (main->warning.verbosity == f_console_verbosity_debug_e) return;
+
+ flockfile(main->warning.to.stream);
+
+ fl_print_format("%r%[%QFailed while calling f_status_string_to() for status%] ", main->output.to.stream, f_string_eol_s, main->context.set.warning, main->context.set.warning, main->context.set.warning);
+ fl_print_format("%[%ui%]", main->output.to.stream, main->context.set.notable, status_of, main->context.set.notable);
+ fl_print_format("%[, failing with status code%] ", main->output.to.stream, main->context.set.warning, status_error, main->context.set.warning);
+ fl_print_format("%[%ui%]", main->output.to.stream, main->context.set.notable, status_error, main->context.set.notable);
+ fl_print_format("%[.%]%r", main->output.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_process_string_to_failed_
+
#ifdef __cplusplus
} // extern "C"
#endif
#endif
/**
+ * Print a message about a packet response.
+ *
+ * @param main
+ * The main program data.
+ * @param data
+ * The control data.
+ * @param header
+ * The control payload packet header data.
+ * @param status
+ * A string representing the name of the status code from header.status.
+ */
+#ifndef _di_control_print_controller_packet_response_
+ extern void control_print_controller_packet_response(fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header, const f_string_static_t string_status) F_attribute_visibility_internal_d;
+#endif // _di_control_print_controller_packet_response_
+
+/**
* Print a message displaying the object and content for some packet header.
*
* @param main
* The control data.
* @param header
* The control payload packet header data.
+ * @param status
+ * A string representing the name of the status code from header.status.
*/
#ifndef _di_control_print_error_packet_response_
- extern void control_print_error_packet_response(fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header) F_attribute_visibility_internal_d;
+ extern void control_print_error_packet_response(fll_program_data_t * const main, control_data_t * const data, const control_payload_header_t header, const f_string_static_t status) F_attribute_visibility_internal_d;
#endif // _di_control_print_error_packet_response_
/**
* Print an error message about no actions being provided.
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_
+/**
+ * Print a warning message about a failure when calling f_status_string_to().
+ *
+ * @param main
+ * The main program data.
+ * @param status_of
+ * The status code to be translating to a string.
+ * @param status_error
+ * The status code representing the failure status returned by f_status_string_to().
+ *
+ * @see f_status_string_to()
+ */
+#ifndef _di_control_print_warning_packet_process_string_to_failed_
+ extern void control_print_warning_packet_process_string_to_failed(fll_program_data_t * const main, const f_status_t status_of, const f_status_t status_error) F_attribute_visibility_internal_d;
+#endif // _di_control_print_warning_packet_process_string_to_failed_
+
#ifdef __cplusplus
} // extern "C"
#endif
--- /dev/null
+# fss-0002
+
+Packet Response:
+ The control program sends packets and receives packet responses from the controller program over the controller program's control socket.
+ This documentation describes the expected response packets and how these response packets are handled.
+
+ The communications to/from the controller program utilize the FSS-000F (Simple Packet).
+ This Simple Packet is expected to contain within it the FSS-000E (Payload) format.
+
+ The Payload contains within it a Header and a Payload.
+ Note the potential confusion here between the Payload when referring to the Packet data format and the Payload referring to the Content within the Payload Packet.
+ To avoid this, henceforth "Payload Packet" refers to the FSS-000E (Payload) format used within the Simple Packet and "Payload Content" refers to the Content within the Payload Packet.
+
+ The Payload Packet (FSS-000E) is very flexible in what it allows within the Header of the Payload Packet.
+ The Control program is more restrictive and supports only a subset of the possibilities (which this is explicitly allowed by the Specification).
+
+ The Control program only supports the following Payload Packet header Objects\:
+ - status: Allowing only a single status header Object.
+ - type: Allowing only a single type header Object and may only be one of: "error" and "controller".
+ - action: Allowing only a single action header Object and may only be one of: "freeze", "kill", "pause", "reboot", "reload", "rerun", "restart", "resume", "shutdown", "start", "stop", and "thaw".
+ - length: Allowing only a single length header Object and must properly describe the length of the entire Payload Packet as per the referenced Specifications.
+
+ The "error" type response Payload Packet is treated as an error response.
+ For any error responses that are associated with an action, then the action header is provided (otherwise it is not expected and is ignored).
+ For any error responses the Payload Content may be empty but when it is not, then the Payload Content is a single string representing a message further describing the error or the reason for the error.
+ These error responses represents errors in attempting to perform some action.
+ These responses are not used for actions that return an error as the result of a proper execution or performing of that action.
+
+ The "controller" type response Payload Packet represents a response regarding the result of performing a requested action.
+ There must always be an "action" designating the action this response is in regards to.
+ Only the following are (currently) supported as a status\:
+ - F_busy: When unable to perform the action as because the service is too busy or the
+ - F_done: When successfully performed the action but the action does not return success or failure.
+ - F_failure: When successfully performed the action and the action returned some sort of failure or error.
+ - F_success: When successfully performed the action and the action returned some sort of success.
+
+ When using the -R/--return parameter, the program prints specially formatted messages to help make the output more scriptable.
+
+ The form is "response [type] [action] [status]".
+ Examples\:
+ - A response that designates the action failed might look like: "response controller my_action F_failure".
+ - A response that designates the controller ran out of memory, preventing the action from being run: "response error my_action F_memory_not".
+ - A response that designates the controller ran successfully: "response controller my_action F_success".
+
+ When the control program fails to function due to some error, there will be no specially formatted message printed.
+ When the controller program fails before it can perform the requested action, then a "response error [action] [status]" formatted message is printed.
+ When the controller program successfully performs the action but the result of that action is an error, then a "response controller [action] F_failure" formatted message is printed.
#
# 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.