From 8b0b7001bdb5a710e92c1f73243b01eb301f27e6 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Mon, 3 Jan 2022 22:14:31 -0600 Subject: [PATCH] Update: Fix bug in socket disconnect, add additional signal functions, and some clean up. The socket close enumerations are being directly passed to shutdown(). This is not correct because they do not directly map. Use the size_read and size_write already provided in the socket file. This allows for the length to be exclusively a write (better practice). Provide f_signal_wait() and f_signal_wait_until() functions that handle sigwaitinfo() and sigtimedwait() respectively. Use uint8_t rather than unsigned short. The fact that there is still a short in use here makes it clear that I have not even glanced at this file in a long long time. --- level_0/f_signal/c/signal.c | 31 ++++++++++++++++++++ level_0/f_signal/c/signal.h | 60 ++++++++++++++++++++++++++++++++++++++ level_0/f_socket/c/socket-common.h | 2 +- level_0/f_socket/c/socket.c | 16 ++++++---- level_0/f_socket/c/socket.h | 4 ++- 5 files changed, 106 insertions(+), 7 deletions(-) diff --git a/level_0/f_signal/c/signal.c b/level_0/f_signal/c/signal.c index e2ffaaa..3a9451a 100644 --- a/level_0/f_signal/c/signal.c +++ b/level_0/f_signal/c/signal.c @@ -25,6 +25,7 @@ extern "C" { } signal->id = 0; + return F_none; } #endif // _di_f_signal_close_ @@ -48,6 +49,7 @@ extern "C" { } signal->id = result; + return F_none; } #endif // _di_f_signal_open_ @@ -230,6 +232,35 @@ extern "C" { } #endif // _di_f_signal_set_has_ +#ifndef _di_f_signal_wait_ + f_status_t f_signal_wait(const sigset_t *set, siginfo_t *information) { + + if (sigwaitinfo(set, information) < 0) { + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_signal_wait_ + +#ifndef _di_f_signal_wait_until_ + f_status_t f_signal_wait_until(const sigset_t *set, const struct timespec *timeout, siginfo_t *information) { + + if (sigtimedwait(set, information, timeout) < 0) { + if (errno == EAGAIN) return F_time_out; + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_signal_wait_until_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_signal/c/signal.h b/level_0/f_signal/c/signal.h index 3c8784a..fe26806 100644 --- a/level_0/f_signal/c/signal.h +++ b/level_0/f_signal/c/signal.h @@ -44,6 +44,7 @@ extern "C" { * F_input_output (with error bit) if an I/O error occurred. * F_interrupt (with error bit) when program received an interrupt signal, halting operation. * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) for any other error. * * @see close() @@ -69,6 +70,7 @@ extern "C" { * F_file_descriptor_max (with error bit) if max file descriptors is reached. * F_memory_not (with error bit) if out of memory. * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) for any other error. * * @see signalfd() @@ -101,6 +103,7 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_input_output (with error bit) on I/O error. * F_file_type_directory (with error bit) if file descriptor represents a directory. + * * F_failure (with error bit) for any other error. * * @see poll() @@ -125,6 +128,7 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_prohibited (with error bit) if not allowed to send signals to the given process. * F_found_not (with error bit) if the given process was not found. + * * F_failure (with error bit) for any other error. * * @see kill() @@ -145,6 +149,7 @@ extern "C" { * F_none on success but no signal found. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) for any other error. * * @see sigaddset() @@ -165,6 +170,7 @@ extern "C" { * F_none on success but no signal found. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) for any other error. * * @see sigdelset() @@ -183,6 +189,7 @@ extern "C" { * F_none on success but no signal found. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) for any other error. * * @see sigemptyset() @@ -201,6 +208,7 @@ extern "C" { * F_none on success but no signal found. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) for any other error. * * @see sigfillset() @@ -228,6 +236,7 @@ extern "C" { * F_none on success but no signal found. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) for any other error. * * @see sigprocmask() @@ -253,6 +262,7 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_resource_not (with error bit) if the max signals is reached. * F_supported_not (with error bit) if this action is not supported by the current OS. + * * F_failure (with error bit) for any other error. * * @see sigqueue() @@ -274,6 +284,7 @@ extern "C" { * F_false if signal is not found. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) for any other error. * * @see sigismember() @@ -282,6 +293,55 @@ extern "C" { extern f_status_t f_signal_set_has(const int signal, const sigset_t *set); #endif // _di_f_signal_set_has_ +/** + * Wait until any signal in a set of signals is received. + * + * @param set + * The set of signals to wait for. + * @param information + * (optional) The resulting signal information. + * Set to NULL to not use. + * + * @return + * F_none if signal is found. + * + * F_interrupt (with error bit) if interrupted by a signal other than one specified in the signal set. + * F_parameter (with error bit) if a parameter is invalid. + * + * F_failure (with error bit) for any other error. + * + * @see sigwaitinfo() + */ +#ifndef _di_f_signal_wait_ + extern f_status_t f_signal_wait(const sigset_t *set, siginfo_t *information); +#endif // _di_f_signal_wait_ + +/** + * Wait until any signal in a set of signals is received until the given time out is reached. + * + * @param set + * The set of signals to wait for. + * @param timeout + * The amount of time to wait. + * @param information + * (optional) The resulting signal information. + * Set to NULL to not use. + * + * @return + * F_none if signal is found before time out. + * F_time_out if no signal is find by the time out. + * + * F_interrupt (with error bit) if interrupted by a signal other than one specified in the signal set. + * F_parameter (with error bit) if a parameter is invalid. + * + * F_failure (with error bit) for any other error. + * + * @see sigtimedwait() + */ +#ifndef _di_f_signal_wait_until_ + extern f_status_t f_signal_wait_until(const sigset_t *set, const struct timespec *timeout, siginfo_t *information); +#endif // _di_f_signal_wait_until_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_socket/c/socket-common.h b/level_0/f_socket/c/socket-common.h index 972c732..a7ca9db 100644 --- a/level_0/f_socket/c/socket-common.h +++ b/level_0/f_socket/c/socket-common.h @@ -34,8 +34,8 @@ extern "C" { * f_socket_close_*: * - fast: Fast Socket close, as in close(). * - read: Read close, as in shutdown(, SHUT_RD). - * - write: Write close, as in shutdown(, SHUT_WR). * - read_write: Read/Write close, as in shutdown(, SHUT_RDWR). + * - write: Write close, as in shutdown(, SHUT_WR). */ #ifndef _di_f_socket_closes_ enum { diff --git a/level_0/f_socket/c/socket.c b/level_0/f_socket/c/socket.c index b3b98d8..f173422 100644 --- a/level_0/f_socket/c/socket.c +++ b/level_0/f_socket/c/socket.c @@ -186,7 +186,7 @@ extern "C" { #endif // _di_f_socket_create_pair_ #ifndef _di_f_socket_disconnect_ - f_status_t f_socket_disconnect(f_socket_t * const socket, const unsigned short action) { + f_status_t f_socket_disconnect(f_socket_t * const socket, const uint8_t action) { #ifndef _di_level_0_parameter_checking_ if (!socket) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ @@ -196,8 +196,14 @@ extern "C" { if (action == f_socket_close_fast_e) { result = close(socket->id); } - else if (action == f_socket_close_read_e || action == f_socket_close_write_e || action == f_socket_close_read_write_e) { - result = shutdown(socket->id, action); + else if (action == f_socket_close_read_e) { + result = shutdown(socket->id, SHUT_RD); + } + else if (action == f_socket_close_write_e) { + result = shutdown(socket->id, SHUT_WR); + } + else if (action == f_socket_close_read_write_e) { + result = shutdown(socket->id, SHUT_RDWR); } else { return F_status_set_error(F_supported_not); @@ -298,7 +304,7 @@ extern "C" { if (!length) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - const ssize_t result = recvfrom(socket->id, buffer, *length, flags, socket->address, &socket->length); + const ssize_t result = recvfrom(socket->id, buffer, socket->size_read, flags, socket->address, &socket->length); if (result < 0) { if (errno == EACCES) return F_status_set_error(F_access_denied); @@ -376,7 +382,7 @@ extern "C" { if (!length) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - const ssize_t result = sendto(socket->id, buffer, *length, flags, socket->address, socket->length); + const ssize_t result = sendto(socket->id, buffer, socket->size_write, flags, socket->address, socket->length); if (result < 0) { if (errno == EACCES) return F_status_set_error(F_access_denied); diff --git a/level_0/f_socket/c/socket.h b/level_0/f_socket/c/socket.h index 5c2d157..23e4acb 100644 --- a/level_0/f_socket/c/socket.h +++ b/level_0/f_socket/c/socket.h @@ -287,7 +287,7 @@ extern "C" { * @see shutdown() */ #ifndef _di_f_socket_disconnect_ - extern f_status_t f_socket_disconnect(f_socket_t * const socket, const unsigned short action); + extern f_status_t f_socket_disconnect(f_socket_t * const socket, const uint8_t action); #endif // _di_f_socket_disconnect_ /** @@ -388,6 +388,7 @@ extern "C" { * @param socket * The socket structure. * The socket.id must represent a valid socket file descriptor. + * The socket.size_read is used to represent the buffer size in buffer and must not be larger than the actual size of the buffer. * @param flags * Read flags. * @param buffer @@ -474,6 +475,7 @@ extern "C" { * @param socket * The socket structure. * The socket.id must represent a valid socket file descriptor. + * The socket.size_write is used to represent the buffer size in buffer and must not be larger than the actual size of the buffer. * @param flags * Read flags. * @param buffer -- 1.8.3.1