extern "C" {
#endif
-#ifndef _di_controller_control_accept_
- f_status_t controller_control_accept(const controller_global_t * const global, controller_control_t * const control) {
-
- /*if (control->client.id != -1) {
- f_socket_disconnect(&control->client, f_socket_close_fast_e);
-
- control->client.id = -1;
- }*/
-
- f_status_t status = f_socket_accept(&control->client, control->server.id);
-
- if (F_status_is_error(status)) {
- f_socket_disconnect(&control->client, f_socket_close_fast_e);
-
- controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_socket_accept", F_true);
-
- return status;
- }
-
- controller_control_configure_client(global, &control->client);
-
- control->input.used = 0;
- control->output.used = 0;
-
- f_char_t buffer[controller_control_default_socket_buffer_d + 1];
- size_t length = 0;
-
- memset(buffer, 0, sizeof(f_char_t) * (controller_control_default_socket_buffer_d + 1));
-
- // Pre-process the packet header.
- control->client.size_read = controller_control_default_socket_header_d;
- status = f_socket_read(&control->client, f_socket_flag_peek_d, buffer, &length);
-
- if (F_status_is_error(status)) {
- f_socket_disconnect(&control->client, f_socket_close_fast_e);
-
- controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_socket_read", F_true);
-
- return status;
- }
-
- if (!length) {
- status = controller_control_respond_error_string(global, control, F_empty, "Received packet is empty.");
-
- f_socket_disconnect(&control->client, f_socket_close_fast_e);
-
- if (F_status_is_error(status)) return status;
-
- return F_valid_not;
- }
-
- if (length < controller_control_default_socket_header_d) {
- status = controller_control_respond_error_string(global, control, F_too_large, "Received packet is too small.");
-
- f_socket_disconnect(&control->client, f_socket_close_fast_e);
-
- if (F_status_is_error(status)) return status;
-
- return F_valid_not;
- }
-
- if (length > controller_control_default_socket_buffer_max_d) {
- status = controller_control_respond_error_string(global, control, F_too_large, "Received packet is too large.");
-
- f_socket_disconnect(&control->client, f_socket_close_fast_e);
-
- if (F_status_is_error(status)) return status;
-
- return F_valid_not;
- }
-
- // @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);
-
- if (packet_flag & controller_control_packet_flag_binary_d) {
- status = controller_control_respond_error_string(global, control, F_supported_not, "Binary is not a currently supported packet mode.");
-
- f_socket_disconnect(&control->client, f_socket_close_fast_e);
-
- if (F_status_is_error(status)) return status;
-
- return F_supported_not;
- }
-
- control->client.size_read = controller_control_default_socket_buffer_d;
-
- // Pre-allocate the input buffer.
- status = f_string_dynamic_increase_by(packet_length, &control->input);
-
- if (F_status_is_error(status)) {
- controller_control_respond_error_string(global, control, F_memory_not, "Failure allocating memory.");
-
- f_socket_disconnect(&control->client, f_socket_close_fast_e);
-
- controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_string_dynamic_increase_by", F_true);
-
- return status;
- }
-
- {
- size_t total = 0;
-
- do {
- status = f_socket_read(&control->client, 0, &control->input, &total);
-
- if (F_status_is_error(status)) {
- controller_control_respond_error_string(global, control, F_status_set_fine(status), "Failure while reading from control->client socket.");
-
- f_socket_disconnect(&control->client, f_socket_close_fast_e);
-
- return F_status_set_fine(status);
- }
-
- } while (total == control->client.size_read);
- }
-
- if (control->input.used != length) {
- controller_control_respond_error_string(global, control, F_valid_not, "Received packet header length did not match actual received packet length.");
-
- f_socket_disconnect(&control->client, f_socket_close_fast_e);
-
- return F_valid_not;
- }
-
- // @todo process the data.
-
- // @todo send any responses.
-
- f_socket_disconnect(&control->client, f_socket_close_fast_e);
-
- // Resize memory when the allocated size is greate than the maximum preferred size.
- // Resizing could potentially copy memory to a new address, so it is assumed to be cheaper to just delete the memory entirely.
- if (control->input.size > controller_control_default_socket_buffer_d) {
- status = f_string_dynamic_resize(0, &control->input);
-
- if (F_status_is_error(status)) {
- controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_string_dynamic_resize", F_true);
-
- return status;
- }
- }
-
- if (control->output.size > controller_control_default_socket_buffer_d) {
- status = f_string_dynamic_resize(0, &control->output);
-
- if (F_status_is_error(status)) {
- controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_string_dynamic_resize", F_true);
-
- return status;
- }
- }
-
- return F_none;
- }
-#endif // _di_controller_control_accept_
-
-#ifndef _di_controller_control_configure_client_
- f_status_t controller_control_configure_client(const controller_global_t * const global, f_socket_t * const client) {
-
- struct timeval time_out;
- time_out.tv_sec = 0;
- time_out.tv_usec = controller_control_default_socket_timeout_d;
-
- f_status_t status = f_socket_option_set(client, 1, f_socket_option_time_out_receive_d, (void *) &time_out, sizeof(struct timeval));
-
- if (F_status_is_error_not(status)) {
- status = f_socket_option_set(client, 1, f_socket_option_time_out_send_d, (void *) &time_out, sizeof(struct timeval));
- }
-
- if (F_status_is_error(status)) {
- controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_socket_option_set", F_true);
- }
-
- return status;
- }
-#endif // _di_controller_control_configure_client_
-
-#ifndef _di_controller_control_configure_server_
- f_status_t controller_control_configure_server(const controller_global_t * const global, f_socket_t * const server) {
-
- const struct linger value = { 1, controller_control_default_socket_linger_d };
-
- const f_status_t status = f_socket_option_set(server, 1, f_socket_option_linger_d, (void *) &value, sizeof(struct linger));
-
- if (F_status_is_error(status)) {
- controller_print_error(global->thread, global->main->error, F_status_set_fine(status), "f_socket_option_set", F_true);
- }
-
- return status;
- }
-#endif // _di_controller_control_configure_server_
-
-#ifndef _di_controller_control_packet_header_flag_
- uint8_t controller_control_packet_header_flag(const f_char_t buffer[]) {
- return (uint8_t) (((buffer[0] & 0x8) ? controller_control_packet_flag_binary_d : 0) | ((buffer[0] & 0x4) ? controller_control_packet_flag_endian_big_d : 0));
- }
-#endif // _di_controller_control_packet_header_flag_
-
-#ifndef _di_controller_control_packet_header_length_
- uint32_t controller_control_packet_header_length(const bool is_big, const f_char_t buffer[]) {
-
- #ifdef _is_F_endian_big
- if (is_big) {
- return (buffer[1] << 24u) | (buffer[2] << 16u) | (buffer[3] << 8u) | buffer[4];
- }
- #else
- if (!is_big) {
- return (buffer[1] << 24u) | (buffer[2] << 16u) | (buffer[3] << 8u) | buffer[4];
- }
- #endif // _is_F_endian_big
-
- return (buffer[4] << 24u) | (buffer[3] << 16u) | (buffer[2] << 8u) | buffer[1];
- }
-#endif // _di_controller_control_packet_header_length_
-
-#ifndef _di_controller_control_respond_build_header_
- f_status_t controller_control_respond_build_header(const controller_global_t * const global, controller_control_t * const control, const f_string_static_t type, const f_string_static_t status, const f_array_length_t length) {
-
- f_status_t status2 = F_none;
-
- const f_state_t state = f_state_t_initialize;
- const f_conversion_data_t data_conversion = macro_f_conversion_data_t_initialize(10, 0, 1);
-
- f_string_statics_t content = f_string_statics_t_initialize;
- f_string_static_t contents[1];
- content.array = contents;
- content.used = 1;
-
- control->cache_1.used = 0;
- control->cache_2.used = 0;
-
- // Header: type.
- if (type.used) {
- contents[0] = type;
-
- status2 = fll_fss_extended_write_string(controller_type_s, content, 0, state, &control->cache_1);
- if (F_status_is_error(status2)) return status2;
- }
-
- // Header: status.
- if (status.used) {
- contents[0] = status;
-
- status2 = fll_fss_extended_write_string(controller_status_s, content, 0, state, &control->cache_1);
- if (F_status_is_error(status2)) return status2;
-
- control->cache_2.used = 0;
- }
-
- // Header: length.
- status2 = f_conversion_number_unsigned_to_string(length, data_conversion, &control->cache_2);
- if (F_status_is_error(status2)) return status2;
-
- contents[0] = control->cache_2;
-
- status2 = fll_fss_extended_write_string(controller_length_s, content, 0, state, &control->cache_1);
- if (F_status_is_error(status2)) return status2;
-
- // Append entire header block to the output.
- status2 = fll_fss_payload_write_string(f_fss_string_header_s, control->cache_1, F_false, 0, state, &control->output);
- if (F_status_is_error(status2)) return status2;
-
- return F_none;
- }
-#endif // _di_controller_control_respond_build_header_
-
-#ifndef _di_controller_control_respond_error_
- f_status_t controller_control_respond_error(const controller_global_t * const global, controller_control_t * const control, const f_status_t status, const f_string_static_t message) {
-
- f_status_t status2 = F_none;
-
- control->output.used = 0;
- control->cache_3.used = 0;
-
- {
- const f_conversion_data_t data_conversion = macro_f_conversion_data_t_initialize(10, 0, 1);
-
- status2 = f_conversion_number_unsigned_to_string(F_status_set_fine(status), data_conversion, &control->cache_3);
- if (F_status_is_error(status2)) return status2;
- }
-
- status2 = controller_control_respond_build_header(global, control, controller_error_s, control->cache_3, message.used);
- if (F_status_is_error(status2)) return status2;
-
- {
- const f_state_t state = f_state_t_initialize;
-
- status2 = fll_fss_payload_write_string(f_fss_string_payload_s, message, F_false, 0, state, &control->output);
- if (F_status_is_error(status2)) return status2;
- }
-
- control->client.size_write = control->output.used;
-
- return f_socket_write(&control->client, 0, control->output.string, 0);
- }
-#endif // _di_controller_control_respond_error_
-
-#ifndef _di_controller_control_respond_error_string_
- f_status_t controller_control_respond_error_string(const controller_global_t * const global, controller_control_t * const control, const f_status_t status, const f_string_t message) {
-
- const f_string_static_t string = macro_f_string_static_t_initialize2(message, strlen(message));
-
- return controller_control_respond_error(global, control, status, string);
- }
-#endif // _di_controller_control_respond_error_string_
-
#ifdef __cplusplus
} // extern "C"
#endif
extern "C" {
#endif
-/**
- * Accept connections from a control socket server.
- *
- * Connectons are processed and actions are performed.
- *
- * @param global
- * The global data.
- * @param control
- * The control data.
- *
- * @return
- * F_none on success.
- * F_valid_not on invalid packet from client (this is not an error with the function itself and so no error bit is set).
- *
- * Errors (with error bit) from: f_socket_accept().
- *
- * @see f_socket_accept()
- */
-#ifndef _di_controller_control_accept_
- extern f_status_t controller_control_accept(const controller_global_t * const global, controller_control_t * const control) F_attribute_visibility_internal_d;
-#endif // _di_controller_control_accept_
-
-/**
- * Configure client socket settings.
- *
- * @param global
- * The global data.
- * @param client
- * The client socket structure.
- *
- * @return
- * F_none on success.
- *
- * Errors (with error bit) from: f_socket_option_set().
- *
- * @see f_socket_option_set()
- */
-#ifndef _di_controller_control_configure_client_
- extern f_status_t controller_control_configure_client(const controller_global_t * const global, f_socket_t * const client) F_attribute_visibility_internal_d;
-#endif // _di_controller_control_configure_client_
-
-/**
- * Configure server socket settings.
- *
- * @param global
- * The global data.
- * @param server
- * The server socket structure.
- *
- * @return
- * F_none on success.
- *
- * Errors (with error bit) from: f_socket_option_set().
- *
- * @see f_socket_option_set()
- */
-#ifndef _di_controller_control_configure_server_
- extern f_status_t controller_control_configure_server(const controller_global_t * const global, f_socket_t * const server) F_attribute_visibility_internal_d;
-#endif // _di_controller_control_configure_server_
-
-/**
- * Given the header buffer, get the flag bits.
- *
- * @param buffer
- * The buffer to read the length of and get the
- *
- * @return
- * The 8-bit number representing the flags.
- */
-#ifndef _di_controller_control_packet_header_flag_
- extern uint8_t controller_control_packet_header_flag(const f_char_t buffer[]) F_attribute_visibility_internal_d;
-#endif // _di_controller_control_packet_header_flag_
-
-/**
- * Given the header buffer, get the length bits.
- *
- * The endianness is automatically detected and swapped by this function to guarantee host order bytes.
- *
- * @param is_big
- * If TRUE, then the length in the buffer is in big endian format.
- * If FALSE, then the length in the buffer is in little endian format.
- * @param buffer
- * The buffer to read the length of and get the
- *
- * @return
- * The 32-bit number representing the length.
- */
-#ifndef _di_controller_control_packet_header_length_
- extern uint32_t controller_control_packet_header_length(const bool is_big, const f_char_t buffer[]) F_attribute_visibility_internal_d;
-#endif // _di_controller_control_packet_header_length_
-
-/**
- * Construct the header portion of the payload.
- *
- * This resets and uses control.cache_1 and control.cache_2.
- * Do not use either of these for passing strings to this function.
- *
- * The results of this function are appended to control.output.
- *
- * @param global
- * The global data.
- * @param control
- * The control data.
- * @param type
- * The packet type.
- * Set type.used to 0 to not add to the header.
- * @param status
- * The status code.
- * Set status.used to 0 to not add to the header.
- * @param length
- * The length of the payload Content.
- * This is always added to the header.
- *
- * @return
- * F_none on success.
- *
- * Errors (with error bit) from: f_conversion_number_unsigned_to_string().
- * Errors (with error bit) from: f_string_append().
- * Errors (with error bit) from: fll_fss_extended_write_string().
- * Errors (with error bit) from: fll_fss_payload_write_string().
- *
- * @see f_conversion_number_unsigned_to_string()
- * @see f_string_append()
- * @see fll_fss_extended_write_string()
- * @see fll_fss_payload_write_string()
- */
-#ifndef _di_controller_control_respond_build_header_
- extern f_status_t controller_control_respond_build_header(const controller_global_t * const global, controller_control_t * const control, const f_string_static_t type, const f_string_static_t status, const f_array_length_t length) F_attribute_visibility_internal_d;
-#endif // _di_controller_control_respond_build_header_
-
-/**
- * Accept connections from a control socket server.
- *
- * Connectons are processed and actions are performed.
- *
- * This resets and uses control.cache_3 and control.output.
- * This calls functions that resets and uses control.cache_1, control.cache_2.
- *
- * Common response error codes:
- * - F_empty: Packet is empty (does not even have headers).
- * - F_packet_not: Packet is not a valid packet.
- * - F_supported_not: Format or action is not supported.
- * - F_too_large: Packet is too large (exceeds max packet length).
- * - F_too_small: Packet is too small (smaller than minimum header length).
- *
- * @param global
- * The global data.
- * @param control
- * The control data.
- * @param status
- * The status code.
- * @param message
- * A status message.
- *
- * @return
- * Result of f_socket_write() on success.
- *
- * Errors (with error bit) from: f_socket_write().
- *
- * @see f_socket_write()
- */
-#ifndef _di_controller_control_respond_error_
- extern f_status_t controller_control_respond_error(const controller_global_t * const global, controller_control_t * const control, const f_status_t status, const f_string_static_t message) F_attribute_visibility_internal_d;
-#endif // _di_controller_control_respond_error_
-
-/**
- * Alternate version of controller_control_respond_error() that accepts f_string_t for message.
- *
- * This calls functions that resets and uses control.cache_1, control.cache_2, control.cache_3, and control.output.
- *
- * @param global
- * The global data.
- * @param control
- * The control data.
- * @param status
- * The status code.
- * @param message
- * A status message.
- * This must be a NULL terminated string so that functions like strlen() may get the length of this string.
- *
- * @return
- * Result of controller_control_respond_error() on success.
- *
- * Errors (with error bit) from: controller_control_respond_error().
- *
- * @see controller_control_respond_error()
- */
-#ifndef _di_controller_control_respond_error_string_
- extern f_status_t controller_control_respond_error_string(const controller_global_t * const global, controller_control_t * const control, const f_status_t status, const f_string_t message) F_attribute_visibility_internal_d;
-#endif // _di_controller_control_respond_error_string_
-
#ifdef __cplusplus
} // extern "C"
#endif