The send f_socket_write_stream() is failing.
Probably due to some incomplete step.
Take advantage of this and implement the retry logic and error handling.
continue; \
}
- #define macro_kt_receive_process_handle_error_exit_1(main, method, name, status, flag, id_data) \
+ #define macro_kt_receive_process_handle_error_exit_1(main, method, network, status, name, flag, id_data) \
if (F_status_is_error(status)) { \
- kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(method), kt_tacocat_receive_s, name, status); \
+ kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(method), kt_tacocat_receive_s, network, status, name); \
\
if (id_data) { \
f_file_close_id(id_data); \
return; \
}
- #define macro_kt_receive_process_begin_handle_error_exit_1(main, method, name, status, flag) \
+ #define macro_kt_receive_process_begin_handle_error_exit_1(main, method, network, status, name, flag) \
if (F_status_is_error(status)) { \
- kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(method), kt_tacocat_receive_s, name, status); \
+ kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(method), kt_tacocat_receive_s, network, status, name); \
\
flag = 0; \
\
return; \
}
- #define macro_kt_send_process_handle_error_exit_1(main, method, name, status, flag) \
+ #define macro_kt_send_process_handle_error_exit_1(main, method, network, status, name, flag) \
if (F_status_is_error(status)) { \
- kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(method), kt_tacocat_send_s, name, status); \
+ kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(method), kt_tacocat_send_s, network, status, name); \
\
return F_done_not; \
}
#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) {
+ f_status_t kt_tacocat_print_error_on(fl_print_t * const print, const f_string_t function, const f_string_static_t on, const f_string_static_t network, const f_status_t status, const f_string_static_t name) {
if (!print) return F_status_set_error(F_output_not);
if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
fl_print_format(f_string_format_Q_single_s.string, 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(f_string_format_Q_single_s.string, print->to, print->set->notable, network, print->set->notable);
+ fl_print_format("%[' with file '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+ fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, name, 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);
#endif // _di_kt_tacocat_print_error_
#ifndef _di_kt_tacocat_print_error_on_buffer_too_large_
- f_status_t kt_tacocat_print_error_on_buffer_too_large(fl_print_t * const print, f_string_static_t on, const f_string_static_t network, const f_number_unsigned_t size_expect, const f_number_unsigned_t size_got) {
+ f_status_t kt_tacocat_print_error_on_buffer_too_large(fl_print_t * const print, const f_string_static_t on, const f_string_static_t network, const f_number_unsigned_t size_expect, const f_number_unsigned_t size_got) {
if (!print) return F_status_set_error(F_output_not);
if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
#endif // _di_kt_tacocat_print_error_on_buffer_too_large_
#ifndef _di_kt_tacocat_print_error_on_file_too_large_
- f_status_t kt_tacocat_print_error_on_file_too_large(fl_print_t * const print, f_string_static_t file, f_string_static_t on, const f_string_static_t network, const f_number_unsigned_t size_expect, const f_number_unsigned_t size_got) {
+ f_status_t kt_tacocat_print_error_on_file_too_large(fl_print_t * const print, f_string_static_t file, const f_string_static_t on, const f_string_static_t network, const f_number_unsigned_t size_expect, const f_number_unsigned_t size_got) {
if (!print) return F_status_set_error(F_output_not);
if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
#endif // _di_kt_tacocat_print_error_on_file_too_large_
#ifndef _di_kt_tacocat_print_error_on_busy_
- f_status_t kt_tacocat_print_error_on_busy(fl_print_t * const print, f_string_static_t on, const f_string_static_t network) {
+ f_status_t kt_tacocat_print_error_on_busy(fl_print_t * const print, const f_string_static_t on, const f_string_static_t network) {
if (!print) return F_status_set_error(F_output_not);
if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
#endif // _di_kt_tacocat_print_error_on_busy_
#ifndef _di_kt_tacocat_print_error_on_file_receive_
- f_status_t kt_tacocat_print_error_on_file_receive(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, const f_string_static_t name, const f_string_static_t operation) {
+ f_status_t kt_tacocat_print_error_on_file_receive(fl_print_t * const print, const f_string_t function, const f_string_static_t on, const f_string_static_t network, const f_status_t status, const f_string_static_t name, const f_string_static_t operation) {
if (!print || !print->custom) return F_status_set_error(F_output_not);
if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
#endif // _di_kt_tacocat_print_error_on_file_receive_
#ifndef _di_kt_tacocat_print_error_on_file_send_
- f_status_t kt_tacocat_print_error_on_file_send(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, const f_string_static_t name, const f_string_static_t operation) {
+ f_status_t kt_tacocat_print_error_on_file_send(fl_print_t * const print, const f_string_t function, const f_string_static_t on, const f_string_static_t network, const f_status_t status, const f_string_static_t name, const f_string_static_t operation) {
if (!print || !print->custom) return F_status_set_error(F_output_not);
if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
}
#endif // _di_kt_tacocat_print_error_on_file_send_
+#ifndef _di_kt_tacocat_print_error_on_max_retries_
+ f_status_t kt_tacocat_print_error_on_max_retries(fl_print_t * const print, const f_string_static_t on, const f_string_static_t network, const f_string_static_t name) {
+
+ if (!print) 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("%[%QMax retry on failure reached while trying to%] ", print->to, print->set->error, print->prefix, print->set->error);
+ fl_print_format(f_string_format_Q_single_s.string, 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(f_string_format_Q_single_s.string, print->to, print->set->notable, network, print->set->notable);
+ fl_print_format("%[' with file '%]", print->to, print->set->error, print->set->error, f_string_eol_s);
+ fl_print_format(f_string_format_Q_single_s.string, print->to, print->set->notable, name, 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_okay;
+ }
+#endif // _di_kt_tacocat_print_error_on_max_retries_
+
#ifndef _di_kt_tacocat_print_error_on_packet_too_small_
- f_status_t kt_tacocat_print_error_on_packet_too_small(fl_print_t * const print, f_string_static_t on, const f_string_static_t network, const f_number_unsigned_t size_expect, const f_number_unsigned_t size_got) {
+ f_status_t kt_tacocat_print_error_on_packet_too_small(fl_print_t * const print, const f_string_static_t on, const f_string_static_t network, const f_number_unsigned_t size_expect, const f_number_unsigned_t size_got) {
if (!print) return F_status_set_error(F_output_not);
if (print->verbosity < f_console_verbosity_error_e) return F_output_not;
* @see fll_error_file_print()
*/
#ifndef _di_kt_tacocat_print_error_on_
- extern 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);
+ extern f_status_t kt_tacocat_print_error_on(fl_print_t * const print, const f_string_t function, const f_string_static_t on, const f_string_static_t network, const f_status_t status, const f_string_static_t name);
#endif // _di_kt_tacocat_print_error_on_
/**
* @see fll_error_file_print()
*/
#ifndef _di_kt_tacocat_print_error_on_buffer_too_large_
- extern f_status_t kt_tacocat_print_error_on_buffer_too_large(fl_print_t * const print, f_string_static_t on, const f_string_static_t network, const f_number_unsigned_t size_expect, const f_number_unsigned_t size_got);
+ extern f_status_t kt_tacocat_print_error_on_buffer_too_large(fl_print_t * const print, const f_string_static_t on, const f_string_static_t network, const f_number_unsigned_t size_expect, const f_number_unsigned_t size_got);
#endif // _di_kt_tacocat_print_error_on_buffer_too_large_
/**
* @see fll_error_file_print()
*/
#ifndef _di_kt_tacocat_print_error_on_file_too_large_
- extern f_status_t kt_tacocat_print_error_on_file_too_large(fl_print_t * const print, f_string_static_t file, f_string_static_t on, const f_string_static_t network, const f_number_unsigned_t size_expect, const f_number_unsigned_t size_got);
+ extern f_status_t kt_tacocat_print_error_on_file_too_large(fl_print_t * const print, f_string_static_t file, const f_string_static_t on, const f_string_static_t network, const f_number_unsigned_t size_expect, const f_number_unsigned_t size_got);
#endif // _di_kt_tacocat_print_error_on_file_too_large_
/**
* @see fll_error_file_print()
*/
#ifndef _di_kt_tacocat_print_error_on_busy_
- extern f_status_t kt_tacocat_print_error_on_busy(fl_print_t * const print, f_string_static_t on, const f_string_static_t network);
+ extern f_status_t kt_tacocat_print_error_on_busy(fl_print_t * const print, const f_string_static_t on, const f_string_static_t network);
#endif // _di_kt_tacocat_print_error_on_busy_
/**
* @see fll_error_file_print()
*/
#ifndef _di_kt_tacocat_print_error_on_file_receive_
- extern f_status_t kt_tacocat_print_error_on_file_receive(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, const f_string_static_t name, const f_string_static_t operation);
+ extern f_status_t kt_tacocat_print_error_on_file_receive(fl_print_t * const print, const f_string_t function, const f_string_static_t on, const f_string_static_t network, const f_status_t status, const f_string_static_t name, const f_string_static_t operation);
#endif // _di_kt_tacocat_print_error_on_file_receive_
/**
* @see fll_error_file_print()
*/
#ifndef _di_kt_tacocat_print_error_on_file_send_
- extern f_status_t kt_tacocat_print_error_on_file_send(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, const f_string_static_t name, const f_string_static_t operation);
+ extern f_status_t kt_tacocat_print_error_on_file_send(fl_print_t * const print, const f_string_t function, const f_string_static_t on, const f_string_static_t network, const f_status_t status, const f_string_static_t name, const f_string_static_t operation);
#endif // _di_kt_tacocat_print_error_on_file_send_
/**
+ * Print error message regarding maximum retries after error reached.
+ *
+ * This could be on any error, such as errors on file load, memory, access, or network failures.
+ *
+ * @param print
+ * The output structure to print to.
+ *
+ * This does not alter print.custom.setting.state.status.
+ * @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 name
+ * Th name of the file.
+ *
+ * @return
+ * F_okay 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_max_retries_
+ extern f_status_t kt_tacocat_print_error_on_max_retries(fl_print_t * const print, const f_string_static_t on, const f_string_static_t network, const f_string_static_t name);
+#endif // _di_kt_tacocat_print_error_on_max_retries_
+
+/**
* Print network-related error message for when the connection is busy.
*
* @param print
* @see fll_error_file_print()
*/
#ifndef _di_kt_tacocat_print_error_on_packet_too_small_
- extern f_status_t kt_tacocat_print_error_on_packet_too_small(fl_print_t * const print, f_string_static_t on, const f_string_static_t network, const f_number_unsigned_t size_expect, const f_number_unsigned_t size_got);
+ extern f_status_t kt_tacocat_print_error_on_packet_too_small(fl_print_t * const print, const f_string_static_t on, const f_string_static_t network, const f_number_unsigned_t size_expect, const f_number_unsigned_t size_got);
#endif // _di_kt_tacocat_print_error_on_packet_too_small_
/**
// Make sure the buffer is large enough for payload processing block reads.
set->status = f_memory_array_increase_by(set->socket.size_read, sizeof(f_char_t), (void **) &set->buffer.string, &set->buffer.used, &set->buffer.size);
- macro_kt_receive_process_handle_error_exit_1(main, f_memory_array_increase_by, set->network, set->status, set->flag, &set->socket.id_data);
+ macro_kt_receive_process_handle_error_exit_1(main, f_memory_array_increase_by, set->network, set->status, set->name, set->flag, &set->socket.id_data);
}
if (set->flag & kt_tacocat_socket_flag_receive_block_payload_e) {
size_t length_read = 0;
set->status = f_socket_read_stream(&set->socket, 0, (void *) set->buffer.string, &length_read);
- macro_kt_receive_process_handle_error_exit_1(main, f_socket_read_stream, set->network, set->status, set->flag, &set->socket.id_data);
+ macro_kt_receive_process_handle_error_exit_1(main, f_socket_read_stream, set->network, set->status, set->name, set->flag, &set->socket.id_data);
if (length_read) {
set->buffer.used = length_read;
// Report the resize error but do not fail.
if (F_status_is_error(set->status)) {
- kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(f_memory_array_resize), kt_tacocat_receive_s, set->network, set->status);
+ kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(f_memory_array_resize), kt_tacocat_receive_s, set->network, set->status, set->name);
}
}
}
set->status = f_socket_accept(&set->socket);
// The socket failed to accept and so there is no data socket id to close.
- macro_kt_receive_process_begin_handle_error_exit_1(main, f_socket_accept, set->network, set->status, set->flag);
+ macro_kt_receive_process_begin_handle_error_exit_1(main, f_socket_accept, set->network, set->status, set->name, set->flag);
set->status = f_memory_array_increase_by(kt_tacocat_packet_peek_d + 1, sizeof(f_char_t), (void **) &set->buffer.string, &set->buffer.used, &set->buffer.size);
- macro_kt_receive_process_begin_handle_error_exit_1(main, f_memory_array_increase_by, set->network, set->status, set->flag);
+ macro_kt_receive_process_begin_handle_error_exit_1(main, f_memory_array_increase_by, set->network, set->status, set->name, set->flag);
set->socket.size_read = kt_tacocat_packet_peek_d;
set->socket.size_read = size_read;
- macro_kt_receive_process_begin_handle_error_exit_1(main, f_socket_read_stream, set->network, set->status, set->flag);
+ macro_kt_receive_process_begin_handle_error_exit_1(main, f_socket_read_stream, set->network, set->status, set->name, set->flag);
set->buffer.used += length_read;
}
set->status = f_fss_simple_packet_extract_range(set->buffer, &set->packet);
- macro_kt_receive_process_begin_handle_error_exit_1(main, f_fss_simple_packet_extract_range, set->network, set->status, set->flag);
+ macro_kt_receive_process_begin_handle_error_exit_1(main, f_fss_simple_packet_extract_range, set->network, set->status, set->name, set->flag);
if (set->status == F_packet_too_small || set->packet.size < kt_tacocat_packet_minimum_d) {
kt_tacocat_print_error_on_packet_too_small(&main->program.error, kt_tacocat_receive_s, set->network, kt_tacocat_packet_peek_d, set->buffer.used);
// Report the resize error but do not fail.
if (F_status_is_error(set->status)) {
- kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(f_memory_array_resize), kt_tacocat_receive_s, set->network, set->status);
+ kt_tacocat_print_error_on(&main->program.error, macro_kt_tacocat_f(f_memory_array_resize), kt_tacocat_receive_s, set->network, set->status, set->name);
}
}
return 0;
}
- if (main->setting.send.array[i].status == F_done) {
- if (ready != F_done_not) {
+ if (F_status_set_fine(main->setting.send.array[i].status) == F_done) {
+ if (F_status_is_error(main->setting.send.array[i].status) || ready != F_done_not) {
ready = F_done;
}
}
else {
// @todo the kt_tacocat_receive_process() and kt_tacocat_send_process() have different return designs, figure out which design to use and be consistent.
// @todo in all cases error or success, when done be sure set->file is closed.
+ // @todo on error during partial transfer either attempt to resend, attempt to send failure packet, or abandon.
if (kt_tacocat_send_process(main, &main->setting.send.array[i]) == F_done) {
- if (ready != F_done_not) {
+ if (F_status_is_error(main->setting.send.array[i].status)) {
+ ++main->setting.send.array[i].retry;
+ }
+ else if (ready != F_done_not) {
ready = F_done;
}
}
else {
- // @todo on error during partial transfer either attempt to resend, attempt to send failure packet, or abandon.
+ if (F_status_is_error(main->setting.send.array[i].status)) {
+ ++main->setting.send.array[i].retry;
+ }
+
ready = F_done_not;
}
}
}
if (F_status_is_error(set->status)) {
- macro_kt_send_process_handle_error_exit_1(main, f_memory_array_increase_by, set->network, set->status, set->flag);
+ macro_kt_send_process_handle_error_exit_1(main, f_memory_array_increase_by, set->network, set->status, set->name, set->flag);
}
// Index 0 is the status.
set->flag = kt_tacocat_socket_flag_send_size_e;
}
+ if (set->retry >= kt_tacocat_startup_retry_max_d) {
+ f_file_close(&set->file);
+ f_socket_disconnect(&set->socket, f_socket_close_write_e);
+
+ // Keep error bit but set state to done to designate that nothing else is to be done.
+ set->status = F_status_set_error(F_done);
+
+ kt_tacocat_print_error_on_max_retries(&main->program.error, kt_tacocat_send_s, set->network, set->name);
+
+ return F_done;
+ }
+
if (set->flag == kt_tacocat_socket_flag_send_size_e) {
// Total is used here to explicitly pass a pointer of off_t rather than a pointer of size_t cast to an off_t.
}
if (F_status_is_error(set->status)) {
- macro_kt_send_process_handle_error_exit_1(main, f_file_read_block, set->network, set->status, set->flag);
+ macro_kt_send_process_handle_error_exit_1(main, f_file_read_block, set->network, set->status, set->name, set->flag);
}
set->abstruses.array[2].value.is.a_unsigned = set->buffer.used - f_fss_payload_object_payload_s.used - f_fss_payload_object_end_s.used;
state_local.data = &set->write_state;
fl_fss_payload_header_map(set->abstruses, &set->headers, &state_local);
- macro_kt_send_process_handle_error_exit_1(main, fl_fss_payload_header_map, set->network, state_local.status, set->flag);
+ macro_kt_send_process_handle_error_exit_1(main, fl_fss_payload_header_map, set->network, state_local.status, set->name, set->flag);
set->flag = kt_tacocat_socket_flag_send_combine_e;
}
}
if (F_status_is_error_not(set->status)) {
- macro_kt_send_process_handle_error_exit_1(main, f_string_dynamic_append, set->network, set->status, set->flag);
+ macro_kt_send_process_handle_error_exit_1(main, f_string_dynamic_append, set->network, set->status, set->name, set->flag);
}
set->header.string[set->header.used] = 0;
if (set->flag == kt_tacocat_socket_flag_send_connect_e) {
set->status = f_socket_connect(set->socket);
- macro_kt_send_process_handle_error_exit_1(main, f_socket_connect, set->network, set->status, set->flag);
+ macro_kt_send_process_handle_error_exit_1(main, f_socket_connect, set->network, set->status, set->name, set->flag);
set->flag = kt_tacocat_socket_flag_send_header_e;
}
size_t written = 0;
set->status = f_socket_write_stream(&set->socket, 0, (void *) (set->header.string + set->size_done), &written);
- macro_kt_send_process_handle_error_exit_1(main, f_socket_write_stream, set->network, set->status, set->flag);
+ macro_kt_send_process_handle_error_exit_1(main, f_socket_write_stream, set->network, set->status, set->name, set->flag);
set->size_done += written;
size_t written = 0;
set->status = f_socket_write_stream(&set->socket, 0, (void *) (set->buffer.string + set->size_done), &written);
- macro_kt_send_process_handle_error_exit_1(main, f_socket_write_stream, set->network, set->status, set->flag);
+ macro_kt_send_process_handle_error_exit_1(main, f_socket_write_stream, set->network, set->status, set->name, set->flag);
set->size_done += written;