From 7145779e70bf22abd1e1f5ac7d2cda7a29b81ea8 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Thu, 6 Jul 2023 22:42:12 -0500 Subject: [PATCH] Progress: Further work in TacocaT. 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. --- sources/c/tacocat/main/common.c | 18 +++++ sources/c/tacocat/main/common/print.c | 6 ++ sources/c/tacocat/main/common/print.h | 6 ++ sources/c/tacocat/main/common/type.c | 18 ++++- sources/c/tacocat/main/common/type.h | 22 ++++-- sources/c/tacocat/main/print/error.c | 26 +++++++ sources/c/tacocat/main/print/error.h | 30 ++++++++ sources/c/tacocat/main/process.c | 129 +++++++++++++++++++++++++++++++++- 8 files changed, 245 insertions(+), 10 deletions(-) diff --git a/sources/c/tacocat/main/common.c b/sources/c/tacocat/main/common.c index e8f5f13..cd652e1 100644 --- a/sources/c/tacocat/main/common.c +++ b/sources/c/tacocat/main/common.c @@ -177,6 +177,16 @@ extern "C" { &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, @@ -219,6 +229,14 @@ extern "C" { 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. diff --git a/sources/c/tacocat/main/common/print.c b/sources/c/tacocat/main/common/print.c index e59f988..01e38a2 100644 --- a/sources/c/tacocat/main/common/print.c +++ b/sources/c/tacocat/main/common/print.c @@ -10,6 +10,12 @@ extern "C" { "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", diff --git a/sources/c/tacocat/main/common/print.h b/sources/c/tacocat/main/common/print.h index e61dbb6..1d42038 100644 --- a/sources/c/tacocat/main/common/print.h +++ b/sources/c/tacocat/main/common/print.h @@ -43,6 +43,12 @@ extern "C" { 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, diff --git a/sources/c/tacocat/main/common/type.c b/sources/c/tacocat/main/common/type.c index 126f4e0..5c13fb7 100644 --- a/sources/c/tacocat/main/common/type.c +++ b/sources/c/tacocat/main/common/type.c @@ -10,12 +10,12 @@ extern "C" { 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); @@ -29,16 +29,28 @@ extern "C" { 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_ diff --git a/sources/c/tacocat/main/common/type.h b/sources/c/tacocat/main/common/type.h index 0461bfe..a77a32a 100644 --- a/sources/c/tacocat/main/common/type.h +++ b/sources/c/tacocat/main/common/type.h @@ -30,16 +30,19 @@ extern "C" { * 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 { @@ -57,10 +60,13 @@ extern "C" { 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 \ @@ -74,9 +80,11 @@ extern "C" { 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_ @@ -133,6 +141,8 @@ extern "C" { /** * Delete the program main setting data. * + * @param program + * The main program data. * @param setting * The program main setting data. * @@ -144,7 +154,7 @@ extern "C" { * 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 diff --git a/sources/c/tacocat/main/print/error.c b/sources/c/tacocat/main/print/error.c index e1ff09d..f8179a3 100644 --- a/sources/c/tacocat/main/print/error.c +++ b/sources/c/tacocat/main/print/error.c @@ -52,6 +52,32 @@ extern "C" { } #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 diff --git a/sources/c/tacocat/main/print/error.h b/sources/c/tacocat/main/print/error.h index 173a224..274bdf3 100644 --- a/sources/c/tacocat/main/print/error.h +++ b/sources/c/tacocat/main/print/error.h @@ -87,6 +87,36 @@ extern "C" { 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 diff --git a/sources/c/tacocat/main/process.c b/sources/c/tacocat/main/process.c index 2ff13dd..3469a2d 100644 --- a/sources/c/tacocat/main/process.c +++ b/sources/c/tacocat/main/process.c @@ -9,15 +9,142 @@ extern "C" { 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_ -- 1.8.3.1