Continue work regarding sockets.
f_compare
f_conversion
f_file
+f_fss
f_network
f_path
f_pipe
build_language c
build_libraries -lc
-build_libraries-individual -lfll_error -lfll_print -lfll_program -lfl_conversion -lfl_print -lf_color -lf_compare -lf_console -lf_conversion -lf_file -lf_memory -lf_network -lf_path -lf_pipe -lf_print -lf_signal -lf_socket -lf_string -lf_type_array -lf_utf
+build_libraries-individual -lfll_error -lfll_print -lfll_program -lfl_conversion -lfl_print -lf_color -lf_compare -lf_console -lf_conversion -lf_file -lf_fss -lf_memory -lf_network -lf_path -lf_pipe -lf_print -lf_signal -lf_socket -lf_string -lf_type_array -lf_utf
build_libraries-individual_thread -lf_thread
build_libraries-level -lfll_2 -lfll_1 -lfll_0
build_libraries-monolithic -lfll
&main->setting.send,
};
- const bool const is_receive[] = {
+ const bool is_receive[] = {
F_true,
F_false,
};
struct hostent host;
f_network_family_ip_t family = f_network_family_ip_t_initialize;
f_number_unsigned_t port = 0;
+ f_number_unsigned_t total = 0;
f_string_static_t address = f_string_static_t_initialize;
for (uint8_t i = 0; i < 2; ++i) {
sets[i]->flags.used = 0;
sets[i]->names.used = 0;
sets[i]->buffers.used = 0;
+ sets[i]->packets.used = 0;
+ sets[i]->files.used = 0;
+ sets[i]->sockets.used = 0;
+ sets[i]->statuss.used = 0;
sets[i]->polls.used = 0;
- main->setting.state.status = f_uint16s_increase_by(main->program.parameters.array[parameters[i]].values.used / 2, &sets[i]->flags);
+ total = main->program.parameters.array[parameters[i]].values.used / 2;
+
+ main->setting.state.status = f_uint16s_increase_by(total, &sets[i]->flags);
macro_setting_load_handle_send_receive_error_continue_1(f_uint16s_increase_by);
- main->setting.state.status = f_string_dynamics_increase_by(main->program.parameters.array[parameters[i]].values.used / 2, &sets[i]->names);
+ main->setting.state.status = f_string_dynamics_increase_by(total, &sets[i]->names);
macro_setting_load_handle_send_receive_error_continue_1(f_string_dynamics_increase_by);
- main->setting.state.status = f_string_dynamics_increase_by(main->program.parameters.array[parameters[i]].values.used / 2, &sets[i]->buffers);
+ main->setting.state.status = f_string_dynamics_increase_by(total, &sets[i]->buffers);
macro_setting_load_handle_send_receive_error_continue_1(f_string_dynamics_increase_by);
- main->setting.state.status = f_files_increase_by(main->program.parameters.array[parameters[i]].values.used / 2, &sets[i]->files);
+ main->setting.state.status = f_fss_simple_packet_ranges_increase_by(total, &sets[i]->packets);
+
+ macro_setting_load_handle_send_receive_error_continue_1(f_fss_simple_packet_ranges_increase_by);
+
+ main->setting.state.status = f_files_increase_by(total, &sets[i]->files);
macro_setting_load_handle_send_receive_error_continue_1(f_files_increase_by);
- main->setting.state.status = f_sockets_increase_by(main->program.parameters.array[parameters[i]].values.used / 2, &sets[i]->sockets);
+ main->setting.state.status = f_sockets_increase_by(total, &sets[i]->sockets);
macro_setting_load_handle_send_receive_error_continue_1(f_sockets_increase_by);
- main->setting.state.status = f_statuss_increase_by(main->program.parameters.array[parameters[i]].values.used / 2, &sets[i]->statuss);
+ main->setting.state.status = f_statuss_increase_by(total, &sets[i]->statuss);
macro_setting_load_handle_send_receive_error_continue_1(f_statuss_increase_by);
- main->setting.state.status = f_polls_increase_by(main->program.parameters.array[parameters[i]].values.used / 2, &sets[i]->polls);
+ main->setting.state.status = f_polls_increase_by(total, &sets[i]->polls);
macro_setting_load_handle_send_receive_error_continue_1(f_polls_increase_by);
sets[i]->flags.array[j] = kt_tacocat_socket_flag_none_e;
sets[i]->names.array[j].used = 0;
sets[i]->buffers.array[j].used = 0;
+ sets[i]->packets.array[j].control.start = 1;
+ sets[i]->packets.array[j].control.stop = 0;
+ sets[i]->packets.array[j].size.start = 1;
+ sets[i]->packets.array[j].size.stop = 0;
+ sets[i]->packets.array[j].payload.start = 1;
+ sets[i]->packets.array[j].payload.stop = 0;
if (main->program.parameters.arguments.array[index].used) {
if (f_path_is_absolute(main->program.parameters.arguments.array[index]) == F_true || f_path_is_relative_current(main->program.parameters.arguments.array[index]) == F_true) {
++sets[i]->statuss.used;
++sets[i]->names.used;
++sets[i]->buffers.used;
+ ++sets[i]->packets.used;
}
else {
main->setting.state.status = F_status_set_error(F_parameter);
}
#endif // _di_kt_tacocat_setting_load_address_port_extract_
+
#ifdef __cplusplus
} // extern "C"
#endif
* - size_receive: The block size in bytes to use when sending packets.
* - size_send: The block size in bytes to use when receiving packets.
*
+ * kt_tacocat_interval_*_d:
+ * - poll: The time in milliseconds to poll for before returning (this is the amount of time poll() blocks).
+ *
+ * kt_tacocat_packet_*_d:
+ * - peek: The size to peek into the packet to get the initial information.
+ * - read: The size to read at a time when processing the packet.
+ *
* kt_tacocat_signal_*_d:
* - check: When not using threads, this is how often to perform the check (lower numbers incur more kernel I/O).
* - check_failsafe: When using threads, how many consecutive failures to check signal before aborting (as a recursion failsafe).
- *
- * kt_tacocat_interval_*_d:
- * - poll: The time in milliseconds to poll for before returning (this is the amount of time poll() blocks).
*/
#ifndef _di_kt_tacocat_d_
#define kt_tacocat_allocation_console_d 4
#define kt_tacocat_block_size_receive_d kt_tacocat_block_size_d
#define kt_tacocat_block_size_send_d kt_tacocat_block_size_d
+ #define kt_tacocat_interval_poll_d 1400 // 1.4 second.
+
+ #define kt_tacocat_packet_peek_d F_fss_simple_packet_block_header_size_d
+ #define kt_tacocat_packet_read_d 8192
+
#define kt_tacocat_signal_check_d 20000
#define kt_tacocat_signal_check_failsafe_d 20000
-
- #define kt_tacocat_interval_poll_d 1400 // 1.4 second.
#endif // _di_kt_tacocat_d_
/**
"f_console_parameter_process",
"f_file_open",
"f_files_increase_by",
+ "f_fss_simple_packet_ranges_increase_by",
"f_network_from_ip_name",
"f_network_is_ip_address",
"f_polls_increase_by",
"f_socket_create",
"f_socket_disconnect",
"f_socket_listen",
+ "f_socket_read_stream",
"f_sockets_increase_by",
"f_statuss_increase_by",
"f_string_append_nulless",
kt_tacocat_f_f_console_parameter_process_e,
kt_tacocat_f_f_file_open_e,
kt_tacocat_f_f_files_increase_by_e,
+ kt_tacocat_f_f_fss_simple_packet_ranges_increase_by_e,
kt_tacocat_f_f_network_from_ip_name_e,
kt_tacocat_f_f_network_is_ip_address_e,
kt_tacocat_f_f_polls_increase_by_e,
kt_tacocat_f_f_socket_create_e,
kt_tacocat_f_f_socket_disconnect_e,
kt_tacocat_f_f_socket_listen_e,
+ kt_tacocat_f_f_socket_read_stream_e,
kt_tacocat_f_f_sockets_increase_by_e,
kt_tacocat_f_f_statuss_increase_by_e,
kt_tacocat_f_f_string_append_nulless_e,
const f_string_static_t kt_tacocat_file_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_file_s, 0, KT_TACOCAT_file_s_length);
const f_string_static_t kt_tacocat_network_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_network_s, 0, KT_TACOCAT_network_s_length);
const f_string_static_t kt_tacocat_network_or_socket_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_network_or_socket_s, 0, KT_TACOCAT_network_or_socket_s_length);
+ const f_string_static_t kt_tacocat_receive_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_receive_s, 0, KT_TACOCAT_receive_s_length);
+ const f_string_static_t kt_tacocat_send_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_send_s, 0, KT_TACOCAT_send_s_length);
const f_string_static_t kt_tacocat_socket_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_socket_s, 0, KT_TACOCAT_socket_s_length);
const f_string_static_t kt_tacocat_tacocat_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_tacocat_s, 0, KT_TACOCAT_tacocat_s_length);
const f_string_static_t kt_tacocat_two_s = macro_f_string_static_t_initialize_1(KT_TACOCAT_two_s, 0, KT_TACOCAT_two_s_length);
#define KT_TACOCAT_file_s "file"
#define KT_TACOCAT_network_s "network"
#define KT_TACOCAT_network_or_socket_s "network / socket"
+ #define KT_TACOCAT_receive_s "receive"
+ #define KT_TACOCAT_send_s "send"
#define KT_TACOCAT_socket_s "socket"
#define KT_TACOCAT_tacocat_s "tacocat"
#define KT_TACOCAT_two_s "two"
#define KT_TACOCAT_file_s_length 4
#define KT_TACOCAT_network_s_length 7
#define KT_TACOCAT_network_or_socket_s_length 16
+ #define KT_TACOCAT_receive_s_length 7
+ #define KT_TACOCAT_send_s_length 4
#define KT_TACOCAT_socket_s_length 6
#define KT_TACOCAT_tacocat_s_length 7
#define KT_TACOCAT_two_s_length 3
extern const f_string_static_t kt_tacocat_file_s;
extern const f_string_static_t kt_tacocat_network_s;
extern const f_string_static_t kt_tacocat_network_or_socket_s;
+ extern const f_string_static_t kt_tacocat_receive_s;
+ extern const f_string_static_t kt_tacocat_send_s;
extern const f_string_static_t kt_tacocat_socket_s;
extern const f_string_static_t kt_tacocat_tacocat_s;
extern const f_string_static_t kt_tacocat_two_s;
for (uint8_t i = 0; i < 2; ++i) {
- for (; j < sets[i]->files.used ; ++j) {
+ for (j = 0; j < sets[i]->files.used ; ++j) {
f_file_close(&sets[i]->files.array[j]);
} // for
- for (; j < sets[i]->sockets.used ; ++j) {
+ for (j = 0; j < sets[i]->sockets.used ; ++j) {
f_socket_disconnect(&sets[i]->sockets.array[j], program.signal_received ? f_socket_close_fast_e : f_socket_close_read_write_e);
} // for
f_string_dynamics_resize(0, &sets[i]->names);
f_string_dynamics_resize(0, &sets[i]->buffers);
+ f_fss_simple_packet_ranges_resize(0, &sets[i]->packets);
} // for
}
*
* names: An array of names for each socket.
* buffers: An array of buffers for sending or receiving data between clients for each socket.
+ * packets: An array of simple packet ranges representing the parts of the packet for each socket for use during processing.
*/
#ifndef _di_kt_tacocat_socket_set_t_
typedef struct {
f_string_dynamics_t names;
f_string_dynamics_t buffers;
+ f_fss_simple_packet_ranges_t packets;
} kt_tacocat_socket_set_t;
#define kt_tacocat_socket_set_t_initialize \
f_statuss_t_initialize, \
f_string_dynamics_t_initialize, \
f_string_dynamics_t_initialize, \
+ f_fss_simple_packet_ranges_t_initialize, \
}
#define macro_kt_tacocat_setting_t_initialize_1(block_size) \
f_statuss_t_initialize, \
f_string_dynamics_t_initialize, \
f_string_dynamics_t_initialize, \
+ f_fss_simple_packet_ranges_t_initialize, \
}
#endif // _di_kt_tacocat_socket_set_t_
}
#endif // _di_kt_tacocat_print_error_file_
+#ifndef _di_kt_tacocat_print_error_on_
+ f_status_t kt_tacocat_print_error_on(fl_print_t * const print, const f_string_t function, f_string_static_t on, const f_string_static_t network, const f_status_t status) {
+
+ if (!print || !print->custom) return F_status_set_error(F_output_not);
+ if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
+
+ f_file_stream_lock(print->to);
+
+ fl_print_format("%[%QNetwork error on%] ", print->to, print->set->error, print->prefix, print->set->error);
+ fl_print_format("%[%Q%]", print->to, print->set->notable, on, print->set->notable);
+ fl_print_format(" %[for '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+ fl_print_format("%[%Q%]", print->to, print->set->notable, network, print->set->notable);
+ fl_print_format(" %['.%]%r", print->to, print->set->error, print->set->error, f_string_eol_s);
+
+ f_file_stream_unlock(print->to);
+
+ fll_error_print(print, F_status_set_fine(status), function, F_true);
+
+ return F_none;
+ }
+#endif // _di_kt_tacocat_print_error_
+
#ifndef _di_kt_tacocat_print_error_parameter_value_resolve_unknown_
f_status_t kt_tacocat_print_error_parameter_value_resolve_unknown(fl_print_t * const print, const f_string_dynamic_t unknown) {
#endif // _di_kt_tacocat_print_error_file_
/**
+ * Print file related error or warning messages.
+ *
+ * @param print
+ * The output structure to print to.
+ *
+ * This does not alter print.custom.setting.state.status.
+ * @param function
+ * The name of the function where the error happened.
+ * Set to 0 to disable.
+ * @param on
+ * The network connection direction, which should either be "receive" or "send".
+ * @param network
+ * The name of the network in which the error is related.
+ * @param status
+ * The status code representing the error.
+ *
+ * @return
+ * F_none on success.
+ * F_output_not on success, but no printing is performed.
+ *
+ * F_output_not (with error bit) if setting is NULL.
+ *
+ * @see fll_error_file_print()
+ */
+#ifndef _di_kt_tacocat_print_error_on_
+ f_status_t kt_tacocat_print_error_on(fl_print_t * const print, const f_string_t function, f_string_static_t on, const f_string_static_t network, const f_status_t status);
+#endif // _di_kt_tacocat_print_error_on_
+
+/**
* Print error message for when an unknown value for the resolve parameter is provided.
*
* @param print
// @todo figure out what f_poll_urgent_e can be.
if (main->setting.receive.polls.array[i].revents & (f_poll_read_e | f_poll_urgent_e)) {
- // @todo call receive
kt_tacocat_receive_process(main, i);
-
- if (F_status_is_error(main->setting.state.status)) {
- // @todo print error.
-
- continue;
- }
+ if (F_status_is_error(main->setting.state.status)) continue;
}
} // for
// @todo handle errors
+ //if (F_status_is_error(main->setting.receive.statuss.array[i])) ... // @todo more work needed to clear error bit when a new read is ready.
} while (F_status_is_error_not(main->setting.status_receive));
}
#ifndef _di_kt_tacocat_receive_process_
void kt_tacocat_receive_process(kt_tacocat_main_t * const main, const f_number_unsigned_t index) {
+ uint16_t * const flag = &main->setting.receive.flags.array[index];
f_socket_t * const socket = &main->setting.receive.sockets.array[index];
f_poll_t * const poll = &main->setting.receive.polls.array[index];
+ f_status_t * const status = &main->setting.receive.statuss.array[index];
+ f_string_dynamic_t * const name = &main->setting.receive.names.array[index];
+ f_string_dynamic_t * const buffer = &main->setting.receive.buffers.array[index];
+ f_fss_simple_packet_range_t * const packet = &main->setting.receive.packets.array[index];
+
+ //if (poll->revents & f_poll_urgent_e) { // handle out of band, via f_socket_flag_out_of_band_e?
+
+ *status = f_string_dynamic_increase_by(socket->size_read, buffer);
+
+ if (F_status_is_error(*status)) {
+ kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(f_string_dynamic_increase_by), kt_tacocat_receive_s, *name, *status);
+
+ return;
+ }
+
+ size_t length = 0;
+
+ // This is a new packet (kt_tacocat_socket_flag_none_e).
+ if (!(*flag)) {
+ buffer->used = 0;
+ }
+
+ *status = f_string_dynamic_increase_by(socket->size_read, buffer);
+
+ if (F_status_is_error(*status)) {
+ kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(f_string_dynamic_increase_by), kt_tacocat_receive_s, *name, *status);
- if (poll->revents & f_poll_urgent_e) {
- // @todo then handle out of band, via f_socket_flag_out_of_band_e.
+ return;
}
+ // This is a new packet (kt_tacocat_socket_flag_none_e).
+ if (!(*flag)) {
+ socket->size_read = kt_tacocat_packet_peek_d;
+ *status = f_socket_read_stream(socket, f_socket_flag_peek_e, (void *) &buffer->string, &length);
+
+ if (F_status_is_error(*status)) {
+ kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(f_socket_read_stream), kt_tacocat_receive_s, *name, *status);
+
+ if (*status == F_connect_not) {
+ // @todo errors like this (or perhaps all errors) need to ensure this function is not called again until the state is reset to prevent infinitely looping on this.
+ }
+
+ return;
+ }
+
+ packet->control.start = 1;
+ packet->control.stop = 0;
+ packet->size.start = 1;
+ packet->size.stop = 0;
+ packet->payload.start = 1;
+ packet->payload.stop = 0;
+
+ *status = f_fss_simple_packet_identify(*buffer, packet);
+
+ return;
+ }
+
+ socket->size_read = kt_tacocat_packet_read_d;
+
+ //kt_tacocat_socket_flag_none_e = 0x0,
+ //kt_tacocat_socket_flag_block_control_e = 0x1,
+ //kt_tacocat_socket_flag_block_payload_e = 0x2,
+
// f_socket_flag_peek_e,
//f_socket_read_stream
}
#include <fll/level_0/compare.h>
#include <fll/level_0/console.h>
#include <fll/level_0/file.h>
+#include <fll/level_0/fss.h>
#include <fll/level_0/network.h>
#include <fll/level_0/path.h>
#include <fll/level_0/pipe.h>