Add socket and status arrays for receiving and sending.
Start calling the socket setup and tear down code.
Have the disconnect on exit disconnect cleanly unless an interrupt is called.
&main->setting.file_sends,
};
+ f_sockets_t * const sockets[] = {
+ &main->setting.socket_receives,
+ &main->setting.socket_sends,
+ };
+
+ f_statuss_t * const statuss[] = {
+ &main->setting.status_receives,
+ &main->setting.status_sends,
+ };
+
const bool const is_receive[] = {
F_true,
F_false,
macro_setting_load_handle_send_receive_error_continue_basic(f_files_increase_by);
+ main->setting.state.status = f_sockets_increase_by(main->program.parameters.array[parameters[i]].values.used / 2, sockets[i]);
+
+ macro_setting_load_handle_send_receive_error_continue_basic(f_sockets_increase_by);
+
+ main->setting.state.status = f_statuss_increase_by(main->program.parameters.array[parameters[i]].values.used / 2, statuss[i]);
+
+ macro_setting_load_handle_send_receive_error_continue_basic(f_statuss_increase_by);
+
for (j = 0; j < main->program.parameters.array[parameters[i]].values.used; j += 2) {
// First parameter value represents the network address or the socket file path.
"f_file_open",
"f_files_increase_by",
"f_network_from_ip_name",
+ "f_socket_close",
+ "f_socket_create",
+ "f_socket_disconnect",
+ "f_socket_listen",
+ "f_sockets_increase_by",
+ "f_statuss_increase_by",
"f_string_append_nulless",
"f_string_dynamic_append_nulless",
"f_string_dynamic_increase_by",
kt_tacocat_f_f_file_open_e,
kt_tacocat_f_f_files_increase_by_e,
kt_tacocat_f_f_network_from_ip_name_e,
+ kt_tacocat_f_f_socket_close_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_sockets_increase_by_e,
+ kt_tacocat_f_f_statuss_increase_by_e,
kt_tacocat_f_f_string_append_nulless_e,
kt_tacocat_f_f_string_dynamic_append_nulless_e,
kt_tacocat_f_f_string_dynamic_increase_by_e,
if (!main) return;
fll_program_data_delete(&main->program);
- kt_tacocat_setting_delete(&main->setting);
+ kt_tacocat_setting_delete(main->program, &main->setting);
}
#endif // _di_kt_tacocat_main_delete_
#ifndef _di_kt_tacocat_setting_delete_
- f_status_t kt_tacocat_setting_delete(kt_tacocat_setting_t * const setting) {
+ f_status_t kt_tacocat_setting_delete(const fll_program_data_t program, kt_tacocat_setting_t * const setting) {
if (!setting) return F_status_set_error(F_parameter);
f_file_close(&setting->file_sends.array[i]);
} // for
+ for (; i < setting->socket_receives.used ; ++i) {
+ f_socket_disconnect(&setting->socket_receives.array[i], program.signal_received ? f_socket_close_fast_e : f_socket_close_read_write_e);
+ } // for
+
+ for (; i < setting->socket_sends.used ; ++i) {
+ f_socket_disconnect(&setting->socket_sends.array[i], program.signal_received ? f_socket_close_fast_e : f_socket_close_read_write_e);
+ } // for
+
f_files_resize(0, &setting->file_receives);
f_files_resize(0, &setting->file_sends);
f_sockets_resize(0, &setting->socket_receives);
f_sockets_resize(0, &setting->socket_sends);
- f_string_dynamic_resize(0, &setting->buffer);
+ f_statuss_resize(0, &setting->status_receives);
+ f_statuss_resize(0, &setting->status_sends);
+
f_string_dynamics_resize(0, &setting->receives);
f_string_dynamics_resize(0, &setting->sends);
+ f_string_dynamic_resize(0, &setting->buffer);
+
return F_none;
}
#endif // _di_kt_tacocat_setting_delete_
* status_thread: A status used eclusively by the threaded signal handler.
* state: The state data used when processing data.
*
- * file_receives: An array of input files.
- * file_sends: An array of output files.
+ * file_receives: An array of files for receiving.
+ * file_sends: An array of files for sending.
*
* socket_receives: An array of the network sockets for receiving.
* socket_sends: An array of the network sockets for sending.
*
- * buffer: A string buffer used for caching purposes.
+ * status_receives: An array of statuses for receiving.
+ * status_sends: An array of statuses for sending.
*
* receives: An array of buffers for receiving data receive clients.
* sends: An array of buffers for sending data send clients.
+ *
+ * buffer: A string buffer used for caching purposes.
*/
#ifndef _di_kt_tacocat_setting_t_
typedef struct {
f_sockets_t socket_receives;
f_sockets_t socket_sends;
- f_string_dynamic_t buffer;
+ f_statuss_t status_receives;
+ f_statuss_t status_sends;
f_string_dynamics_t receives;
f_string_dynamics_t sends;
+
+ f_string_dynamic_t buffer;
} kt_tacocat_setting_t;
#define kt_tacocat_setting_t_initialize \
f_files_t_initialize, \
f_sockets_t_initialize, \
f_sockets_t_initialize, \
- f_string_dynamic_t_initialize, \
+ f_statuss_t_initialize, \
+ f_statuss_t_initialize, \
f_string_dynamics_t_initialize, \
f_string_dynamics_t_initialize, \
+ f_string_dynamic_t_initialize, \
}
#endif // _di_kt_tacocat_setting_t_
/**
* Delete the program main setting data.
*
+ * @param program
+ * The main program data.
* @param setting
* The program main setting data.
*
* F_parameter (with error bit) if a parameter is invalid.
*/
#ifndef _di_kt_tacocat_setting_delete_
- extern f_status_t kt_tacocat_setting_delete(kt_tacocat_setting_t * const setting);
+ extern f_status_t kt_tacocat_setting_delete(const fll_program_data_t program, kt_tacocat_setting_t * const setting);
#endif // _di_kt_tacocat_setting_delete_
#ifdef __cplusplus
}
#endif // _di_kt_tacocat_print_error_parameter_value_resolve_unknown_
+#ifndef _di_kt_tacocat_print_error_setting_socket_lengths_must_match_
+ f_status_t kt_tacocat_print_error_setting_socket_lengths_must_match(fl_print_t * const print, const f_string_dynamic_t name, const f_number_unsigned_t names, const f_number_unsigned_t files, const f_number_unsigned_t sockets, const f_number_unsigned_t statuss) {
+
+ 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("%[%QThe lengths of all%] ", print->to, print->set->error, print->prefix, print->set->error);
+ fl_print_format("%[%Q%]", print->to, print->set->notable, name, print->set->notable);
+ fl_print_format(" %[arrays do not have the same length, name array length is '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+ fl_print_format("%[%ul%]", print->to, print->set->notable, names, print->set->notable);
+ fl_print_format("%', the file array length is '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+ fl_print_format("%[%ul%]", print->to, print->set->notable, files, print->set->notable);
+ fl_print_format(" %[', the socket array length is '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+ fl_print_format("%[%ul%]", print->to, print->set->notable, sockets, print->set->notable);
+ fl_print_format(" %[', and the status array length is '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+ fl_print_format("%[%ul%]", print->to, print->set->notable, statuss, 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);
+
+ return F_none;
+ }
+#endif // _di_kt_tacocat_print_error_setting_socket_lengths_must_match_
+
#ifdef __cplusplus
} // extern "C"
#endif
extern 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_parameter_value_resolve_unknown_
+/**
+ * Print error message for when an the different socket relating structure arrays do not have the same length.
+ *
+ * @param print
+ * The output structure to print to.
+ *
+ * This does not alter print.custom.setting.state.status.
+ * @param name
+ * The name of the set of arrays that must have the same length.
+ * @param names
+ * The length of the names array.
+ * @param files
+ * The length of the files array.
+ * @param sockets
+ * The length of the sockets array.
+ * @param statuss
+ * The length of the statuss array.
+ *
+ * @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_setting_socket_lengths_must_match_
+ extern f_status_t kt_tacocat_print_error_setting_socket_lengths_must_match(fl_print_t * const print, const f_string_dynamic_t name, const f_number_unsigned_t names, const f_number_unsigned_t files, const f_number_unsigned_t sockets, const f_number_unsigned_t statuss);
+#endif // _di_kt_tacocat_print_error_setting_socket_lengths_must_match_
+
#ifdef __cplusplus
} // extern "C"
#endif
if (!main) return;
+ if (main->setting.socket_receives.used != main->setting.file_receives.used && main->setting.socket_receives.used != main->setting.receives.used && main->setting.socket_receives.used != main->setting.status_receives.used) {
+ main->setting.state.status = F_status_set_error(F_parameter);
+
+ kt_tacocat_print_error_setting_socket_lengths_must_match(&main->program.error, kt_tacocat_long_receive_s, main->setting.receives.used, main->setting.file_receives.used, main->setting.socket_receives.used, main->setting.status_receives.used);
+
+ return;
+ }
+
+ if (main->setting.socket_sends.used != main->setting.file_sends.used && main->setting.socket_sends.used != main->setting.sends.used && main->setting.socket_sends.used != main->setting.status_sends.used) {
+ main->setting.state.status = F_status_set_error(F_parameter);
+
+ kt_tacocat_print_error_setting_socket_lengths_must_match(&main->program.error, kt_tacocat_long_send_s, main->setting.sends.used, main->setting.file_sends.used, main->setting.socket_sends.used, main->setting.status_sends.used);
+
+ return;
+ }
+
f_number_unsigned_t i = 0;
+ // @todo Make this threaded, if threading is enabled (if threading is disabled then fork).
+ // TacocaT is intended to be simple, so be lazy and create a thread/fork for every single receive and send.
+
+ // Create socket and connect to socket (bind / listen).
+ for (; i < main->setting.socket_receives.used; ++i) {
+
+ if (kt_tacocat_signal_check(main)) return;
+
+ // @todo check to see if connection is one of "local", "inet" (ipv4), or "inet6" (ipv6) and configure socket appropriately.
+
+ main->setting.status_receives.array[i] = f_socket_create(&main->setting.socket_receives.array[i]);
+
+ if (F_status_is_error(main->setting.status_receives.array[i])) {
+ main->setting.state.status = main->setting.status_receives.array[i];
+
+ kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_socket_create));
+
+ continue;
+ }
+
+ main->setting.status_receives.array[i] = f_socket_listen(&main->setting.socket_receives.array[i], 100); // @todo setup a max back log define rather than hardcode 100 here (and 100 is arbitrarily chosen).
+
+ if (F_status_is_error(main->setting.status_receives.array[i])) {
+ main->setting.state.status = main->setting.status_receives.array[i];
+
+ kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_socket_listen));
+
+ continue;
+ }
+ } // for
+
+ for (i = 0; i < main->setting.socket_sends.used; ++i) {
+
+ if (kt_tacocat_signal_check(main)) return;
+
+ // @todo check to see if connection is one of "local", "inet" (ipv4), or "inet6" (ipv6) and configure socket appropriately.
+
+ main->setting.status_sends.array[i] = f_socket_create(&main->setting.socket_sends.array[i]);
+
+ if (F_status_is_error(main->setting.status_sends.array[i])) {
+ main->setting.state.status = main->setting.status_sends.array[i];
+
+ kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_socket_create));
+
+ continue;
+ }
+
+ // @todo f_socket_bind().
+ } // for
+
+ // domain
+ // PF_INET = ipv4
+ // PF_INET6 = ipv6
+ // type
+ // SOCK_STREAM
+ // SOCK_DGRAM
+ // "struct sockaddr", "struct sockaddr_un", or "struct sockaddr_in"
+ // protocol
+ // f_socket_protocol_tcp
+ // f_socket_protocol_udp
+
+ //f_socket_connect
+
// @todo:
// 1: Establish connections.
// 2: read / write from files.
// 3: work or wait until told to terminate.
// 4: terminate.
- main->setting.state.status = F_none;
+ // Disconnect.
+ for (; i < main->setting.socket_receives.used; ++i) {
+
+ if (kt_tacocat_signal_check(main)) return;
+
+ main->setting.status_receives.array[i] = f_socket_disconnect(&main->setting.socket_receives.array[i], f_socket_close_read_write_e);
+
+ if (F_status_is_error(main->setting.status_receives.array[i])) {
+ main->setting.state.status = main->setting.status_receives.array[i];
+
+ kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_socket_disconnect));
+ }
+ } // for
+
+ for (i = 0; i < main->setting.socket_sends.used; ++i) {
+
+ if (kt_tacocat_signal_check(main)) return;
+
+ main->setting.status_sends.array[i] = f_socket_disconnect(&main->setting.socket_sends.array[i], f_socket_close_read_write_e);
+
+ if (F_status_is_error(main->setting.status_sends.array[i])) {
+ main->setting.state.status = main->setting.status_sends.array[i];
+
+ kt_tacocat_print_error(&main->program.error, macro_kt_tacocat_f(f_socket_disconnect));
+ }
+ } // for
+
+ // Handle returning errors.
+ if (F_status_is_error_not(main->setting.state.status)) {
+ main->setting.state.status = F_none;
+
+ for (i = 0; i < main->setting.socket_receives.used; ++i) {
+
+ if (kt_tacocat_signal_check(main)) return;
+
+ if (F_status_is_error(main->setting.status_receives.array[i])) {
+ main->setting.state.status = main->setting.status_receives.array[i];
+ }
+ } // for
+
+ for (i = 0; i < main->setting.socket_sends.used; ++i) {
+
+ if (kt_tacocat_signal_check(main)) return;
+
+ if (F_status_is_error(main->setting.status_sends.array[i])) {
+ main->setting.state.status = main->setting.status_sends.array[i];
+ }
+ } // for
+ }
}
#endif // _di_kt_tacocat_process_main_