From: Kevin Day Date: Mon, 11 Dec 2023 06:26:27 +0000 (-0600) Subject: Update: Socket size_read/size_write checks, result == -1, and explicit passing .generic. X-Git-Tag: 0.7.0~316 X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=ea5f6d56fd8fe3ad71b1b4d264ed0c8bb5e96fd2;p=fll Update: Socket size_read/size_write checks, result == -1, and explicit passing .generic. Make sure size_read and size_write are not 0. If either is 0, then return F_data_not. Make sure the result checks are "== -1" rather than "< 0". Explicitly pass .generic for the address union. This probably isn't necessary but being explicit seems safer. The memory address of the address union, regardless of the union type being used, is cast to 'struct sockaddr' in most cases. This makes the use of ".generic" very practical. Add documentation comment about F_pipe being returned. Problems with the address unions ".sin_family" must be set or unclear F_pipe errors are returned. I may in a future commit perform this assignment during setup because the "form" parameter makes this practical and reasonable to do. --- diff --git a/level_0/f_socket/c/socket.c b/level_0/f_socket/c/socket.c index 8289c5897..476bc8fcd 100644 --- a/level_0/f_socket/c/socket.c +++ b/level_0/f_socket/c/socket.c @@ -10,7 +10,7 @@ extern "C" { if (!socket) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - const int result = accept(socket->id, (struct sockaddr *) &socket->address, &socket->length); + const int result = accept(socket->id, (struct sockaddr *) &socket->address.generic, &socket->length); if (result == -1) { if (errno == EACCES) return F_status_set_error(F_access_denied); @@ -495,7 +495,7 @@ extern "C" { if (!socket) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (getpeername(socket->id, (struct sockaddr *) &socket->address, &socket->length) == -1) { + if (getpeername(socket->id, (struct sockaddr *) &socket->address.generic, &socket->length) == -1) { if (errno == EBADF) return F_status_set_error(F_file_descriptor); if (errno == EFAULT) return F_status_set_error(F_buffer); if (errno == EINVAL) return F_status_set_error(F_parameter); @@ -517,9 +517,11 @@ extern "C" { if (!buffer) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - const ssize_t result = recvfrom(socket->id_data, buffer, socket->size_read, flags, (struct sockaddr *) &socket->address, &socket->length); + if (!socket->size_read) return F_data_not; - if (result < 0) { + const ssize_t result = recvfrom(socket->id_data, buffer, socket->size_read, flags, (struct sockaddr *) &socket->address.generic, &socket->length); + + if (result == -1) { if (errno == EACCES) return F_status_set_error(F_access_denied); if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); if (errno == EALREADY) return F_status_set_error(F_complete_not); @@ -556,9 +558,11 @@ extern "C" { if (!header) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ + if (!socket->size_read) return F_data_not; + const ssize_t result = recvmsg(socket->id_data, header, flags); - if (result < 0) { + if (result == -1) { if (errno == EACCES) return F_status_set_error(F_access_denied); if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); if (errno == EALREADY) return F_status_set_error(F_complete_not); @@ -595,9 +599,11 @@ extern "C" { if (!buffer) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ + if (!socket->size_read) return F_data_not; + const ssize_t result = recv(socket->id_data, buffer, socket->size_read, flags); - if (result < 0) { + if (result == -1) { if (errno == EACCES) return F_status_set_error(F_access_denied); if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); if (errno == EALREADY) return F_status_set_error(F_complete_not); @@ -634,9 +640,11 @@ extern "C" { if (!buffer) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - const ssize_t result = sendto(socket->id_data, buffer, socket->size_write, flags, (struct sockaddr *) &socket->address, socket->length); + if (!socket->size_write) return F_data_not; - if (result < 0) { + const ssize_t result = sendto(socket->id_data, buffer, socket->size_write, flags, (struct sockaddr *) &socket->address.generic, socket->length); + + if (result == -1) { if (errno == EACCES) return F_status_set_error(F_access_denied); if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); if (errno == EALREADY) return F_status_set_error(F_complete_not); @@ -676,9 +684,11 @@ extern "C" { if (!header) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ + if (!socket->size_write) return F_data_not; + const ssize_t result = sendmsg(socket->id_data, header, flags); - if (result < 0) { + if (result == -1) { if (errno == EACCES) return F_status_set_error(F_access_denied); if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); if (errno == EALREADY) return F_status_set_error(F_complete_not); @@ -718,9 +728,11 @@ extern "C" { if (!buffer) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ + if (!socket->size_write) return F_data_not; + const ssize_t result = send(socket->id_data, buffer, socket->size_write, flags); - if (result < 0) { + if (result == -1) { if (errno == EACCES) return F_status_set_error(F_access_denied); if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); if (errno == EALREADY) return F_status_set_error(F_complete_not); diff --git a/level_0/f_socket/c/socket.h b/level_0/f_socket/c/socket.h index 66febd222..ce33bf07d 100644 --- a/level_0/f_socket/c/socket.h +++ b/level_0/f_socket/c/socket.h @@ -538,6 +538,7 @@ extern "C" { * * @return * F_okay on success. + * F_data_not on success, but read size is 0 and so nothing was read. * * F_access_denied (with error bit) on access denied. * F_complete_not (with error bit) if an existing connection is not yet complete. @@ -587,6 +588,7 @@ extern "C" { * * @return * F_okay on success. + * F_data_not on success, but read size is 0 and so nothing was read. * * F_access_denied (with error bit) on access denied. * F_complete_not (with error bit) if an existing connection is not yet complete. @@ -640,6 +642,7 @@ extern "C" { * * @return * F_okay on success. + * F_data_not on success, but read size is 0 and so nothing was read. * * F_access_denied (with error bit) on access denied. * F_complete_not (with error bit) if an existing connection is not yet complete. @@ -693,6 +696,7 @@ extern "C" { * * @return * F_okay on success. + * F_data_not on success, but write size is 0 and so nothing was written. * * F_access_denied (with error bit) on access denied. * F_address_not (with error bit) if no address is provided and the connection is not "connection-mode". @@ -709,7 +713,7 @@ extern "C" { * F_memory_not (with error bit) if out of memory. * F_option_not (with error bit) if a flag is not supported. * F_parameter (with error bit) if a parameter is invalid. - * F_pipe (with error bit) if the local end of a connection oriented socket is closed or SIGPIPE is received. + * F_pipe (with error bit) if the local end of a connection oriented socket is closed or SIGPIPE is received (Linux might return this isntead if F_connect_not). * F_prohibited (with error bit) if the insufficient privileges to perform send. * F_size (with error bit) if size of message makes atomically sending message impossible on a socket type that requires this to be atomic. * F_socket_not (with error bit) if the ID is not a socket descriptor. @@ -746,6 +750,7 @@ extern "C" { * * @return * F_okay on success. + * F_data_not on success, but write size is 0 and so nothing was written. * * F_access_denied (with error bit) on access denied. * F_address_not (with error bit) if no address is provided and the connection is not "connection-mode". @@ -762,7 +767,7 @@ extern "C" { * F_memory_not (with error bit) if out of memory. * F_option_not (with error bit) if a flag is not supported. * F_parameter (with error bit) if a parameter is invalid. - * F_pipe (with error bit) if the local end of a connection oriented socket is closed or SIGPIPE is received. + * F_pipe (with error bit) if the local end of a connection oriented socket is closed or SIGPIPE is received (Linux might return this isntead if F_connect_not). * F_prohibited (with error bit) if the insufficient privileges to perform send. * F_size (with error bit) if size of message makes atomically sending message impossible on a socket type that requires this to be atomic. * F_socket_not (with error bit) if the ID is not a socket descriptor. @@ -803,6 +808,7 @@ extern "C" { * * @return * F_okay on success. + * F_data_not on success, but write size is 0 and so nothing was written. * * F_access_denied (with error bit) on access denied. * F_address_not (with error bit) if no address is provided and the connection is not "connection-mode". @@ -819,7 +825,7 @@ extern "C" { * F_memory_not (with error bit) if out of memory. * F_option_not (with error bit) if a flag is not supported. * F_parameter (with error bit) if a parameter is invalid. - * F_pipe (with error bit) if the local end of a connection oriented socket is closed or SIGPIPE is received. + * F_pipe (with error bit) if the local end of a connection oriented socket is closed or SIGPIPE is received (Linux might return this isntead if F_connect_not). * F_prohibited (with error bit) if the insufficient privileges to perform send. * F_size (with error bit) if size of message makes atomically sending message impossible on a socket type that requires this to be atomic. * F_socket_not (with error bit) if the ID is not a socket descriptor. diff --git a/level_0/f_socket/tests/unit/c/test-socket-read.c b/level_0/f_socket/tests/unit/c/test-socket-read.c index 71fbfb8a4..687835045 100644 --- a/level_0/f_socket/tests/unit/c/test-socket-read.c +++ b/level_0/f_socket/tests/unit/c/test-socket-read.c @@ -91,6 +91,30 @@ void test__f_socket_read__parameter_checking(void **state) { } } +void test__f_socket_read__returns_data_not(void **state) { + + char * const buffer = "test"; + + { + f_socket_t socket = f_socket_t_initialize; + socket.size_read = 0; + + const f_status_t status = f_socket_read(&socket, 0, (void *) buffer, 0); + + assert_int_equal(status, F_data_not); + } + + { + size_t length = 0; + f_socket_t socket = f_socket_t_initialize; + socket.size_read = 0; + + const f_status_t status = f_socket_read(&socket, 0, (void *) buffer, &length); + + assert_int_equal(status, F_data_not); + } +} + void test__f_socket_read__works(void **state) { f_socket_t socket = f_socket_t_initialize; diff --git a/level_0/f_socket/tests/unit/c/test-socket-read.h b/level_0/f_socket/tests/unit/c/test-socket-read.h index 1433a0a96..0189a7c95 100644 --- a/level_0/f_socket/tests/unit/c/test-socket-read.h +++ b/level_0/f_socket/tests/unit/c/test-socket-read.h @@ -24,6 +24,13 @@ extern void test__f_socket_read__fails(void **state); */ extern void test__f_socket_read__parameter_checking(void **state); +/** + * Test that the function returns F_data_not. + * + * @see f_socket_read() + */ +extern void test__f_socket_read__returns_data_not(void **state); + /** * Test that function works. * diff --git a/level_0/f_socket/tests/unit/c/test-socket-read_message.c b/level_0/f_socket/tests/unit/c/test-socket-read_message.c index 1f5bfd329..fd65e0f96 100644 --- a/level_0/f_socket/tests/unit/c/test-socket-read_message.c +++ b/level_0/f_socket/tests/unit/c/test-socket-read_message.c @@ -94,6 +94,32 @@ void test__f_socket_read_message__parameter_checking(void **state) { } } +void test__f_socket_read_message__returns_data_not(void **state) { + + struct msghdr header; + + memset(&header, 0, sizeof(struct msghdr)); + + { + f_socket_t socket = f_socket_t_initialize; + socket.size_read = 0; + + const f_status_t status = f_socket_read_message(&socket, 0, &header, 0); + + assert_int_equal(status, F_data_not); + } + + { + size_t length = 0; + f_socket_t socket = f_socket_t_initialize; + socket.size_read = 0; + + const f_status_t status = f_socket_read_message(&socket, 0, &header, &length); + + assert_int_equal(status, F_data_not); + } +} + void test__f_socket_read_message__works(void **state) { f_socket_t socket = f_socket_t_initialize; diff --git a/level_0/f_socket/tests/unit/c/test-socket-read_message.h b/level_0/f_socket/tests/unit/c/test-socket-read_message.h index 67883e584..3393b0a06 100644 --- a/level_0/f_socket/tests/unit/c/test-socket-read_message.h +++ b/level_0/f_socket/tests/unit/c/test-socket-read_message.h @@ -24,6 +24,13 @@ extern void test__f_socket_read_message__fails(void **state); */ extern void test__f_socket_read_message__parameter_checking(void **state); +/** + * Test that the function returns F_data_not. + * + * @see f_socket_read_message() + */ +extern void test__f_socket_read_message__returns_data_not(void **state); + /** * Test that function works. * diff --git a/level_0/f_socket/tests/unit/c/test-socket-read_stream.c b/level_0/f_socket/tests/unit/c/test-socket-read_stream.c index e21fb24b3..d2fa6d0e4 100644 --- a/level_0/f_socket/tests/unit/c/test-socket-read_stream.c +++ b/level_0/f_socket/tests/unit/c/test-socket-read_stream.c @@ -91,6 +91,30 @@ void test__f_socket_read_stream__parameter_checking(void **state) { } } +void test__f_socket_read_stream__returns_data_not(void **state) { + + char * const buffer = "test"; + + { + f_socket_t socket = f_socket_t_initialize; + socket.size_read = 0; + + const f_status_t status = f_socket_read_stream(&socket, 0, (void *) buffer, 0); + + assert_int_equal(status, F_data_not); + } + + { + size_t length = 0; + f_socket_t socket = f_socket_t_initialize; + socket.size_read = 0; + + const f_status_t status = f_socket_read_stream(&socket, 0, (void *) buffer, &length); + + assert_int_equal(status, F_data_not); + } +} + void test__f_socket_read_stream__works(void **state) { f_socket_t socket = f_socket_t_initialize; diff --git a/level_0/f_socket/tests/unit/c/test-socket-read_stream.h b/level_0/f_socket/tests/unit/c/test-socket-read_stream.h index 67c3c75e3..1790043aa 100644 --- a/level_0/f_socket/tests/unit/c/test-socket-read_stream.h +++ b/level_0/f_socket/tests/unit/c/test-socket-read_stream.h @@ -24,6 +24,13 @@ extern void test__f_socket_read_stream__fails(void **state); */ extern void test__f_socket_read_stream__parameter_checking(void **state); +/** + * Test that the function returns F_data_not. + * + * @see f_socket_read_stream() + */ +extern void test__f_socket_read_stream__returns_data_not(void **state); + /** * Test that function works. * diff --git a/level_0/f_socket/tests/unit/c/test-socket-write.c b/level_0/f_socket/tests/unit/c/test-socket-write.c index 3b6d8c317..ee791b013 100644 --- a/level_0/f_socket/tests/unit/c/test-socket-write.c +++ b/level_0/f_socket/tests/unit/c/test-socket-write.c @@ -97,6 +97,30 @@ void test__f_socket_write__parameter_checking(void **state) { } } +void test__f_socket_write__returns_data_not(void **state) { + + char * const buffer = "test"; + + { + f_socket_t socket = f_socket_t_initialize; + socket.size_write = 0; + + const f_status_t status = f_socket_write(&socket, 0, (void *) buffer, 0); + + assert_int_equal(status, F_data_not); + } + + { + size_t length = 0; + f_socket_t socket = f_socket_t_initialize; + socket.size_write = 0; + + const f_status_t status = f_socket_write(&socket, 0, (void *) buffer, &length); + + assert_int_equal(status, F_data_not); + } +} + void test__f_socket_write__works(void **state) { f_socket_t socket = f_socket_t_initialize; diff --git a/level_0/f_socket/tests/unit/c/test-socket-write.h b/level_0/f_socket/tests/unit/c/test-socket-write.h index d87c4eaf7..6a3d3448d 100644 --- a/level_0/f_socket/tests/unit/c/test-socket-write.h +++ b/level_0/f_socket/tests/unit/c/test-socket-write.h @@ -24,6 +24,13 @@ extern void test__f_socket_write__fails(void **state); */ extern void test__f_socket_write__parameter_checking(void **state); +/** + * Test that the function returns F_data_not. + * + * @see f_socket_write() + */ +extern void test__f_socket_write__returns_data_not(void **state); + /** * Test that function works. * diff --git a/level_0/f_socket/tests/unit/c/test-socket-write_message.c b/level_0/f_socket/tests/unit/c/test-socket-write_message.c index c300c3941..3056e8275 100644 --- a/level_0/f_socket/tests/unit/c/test-socket-write_message.c +++ b/level_0/f_socket/tests/unit/c/test-socket-write_message.c @@ -100,6 +100,32 @@ void test__f_socket_write_message__parameter_checking(void **state) { } } +void test__f_socket_write_message__returns_data_not(void **state) { + + struct msghdr header; + + memset(&header, 0, sizeof(struct msghdr)); + + { + f_socket_t socket = f_socket_t_initialize; + socket.size_write = 0; + + const f_status_t status = f_socket_write_message(&socket, 0, &header, 0); + + assert_int_equal(status, F_data_not); + } + + { + size_t length = 0; + f_socket_t socket = f_socket_t_initialize; + socket.size_write = 0; + + const f_status_t status = f_socket_write_message(&socket, 0, &header, &length); + + assert_int_equal(status, F_data_not); + } +} + void test__f_socket_write_message__works(void **state) { f_socket_t socket = f_socket_t_initialize; diff --git a/level_0/f_socket/tests/unit/c/test-socket-write_message.h b/level_0/f_socket/tests/unit/c/test-socket-write_message.h index b96350fdb..475dc4078 100644 --- a/level_0/f_socket/tests/unit/c/test-socket-write_message.h +++ b/level_0/f_socket/tests/unit/c/test-socket-write_message.h @@ -24,6 +24,13 @@ extern void test__f_socket_write_message__fails(void **state); */ extern void test__f_socket_write_message__parameter_checking(void **state); +/** + * Test that the function returns F_data_not. + * + * @see f_socket_write_message() + */ +extern void test__f_socket_write_message__returns_data_not(void **state); + /** * Test that function works. * diff --git a/level_0/f_socket/tests/unit/c/test-socket-write_stream.c b/level_0/f_socket/tests/unit/c/test-socket-write_stream.c index f3b6511ca..744c8aabb 100644 --- a/level_0/f_socket/tests/unit/c/test-socket-write_stream.c +++ b/level_0/f_socket/tests/unit/c/test-socket-write_stream.c @@ -97,6 +97,30 @@ void test__f_socket_write_stream__parameter_checking(void **state) { } } +void test__f_socket_write_stream__returns_data_not(void **state) { + + char * const buffer = "test"; + + { + f_socket_t socket = f_socket_t_initialize; + socket.size_write = 0; + + const f_status_t status = f_socket_write_stream(&socket, 0, (void *) buffer, 0); + + assert_int_equal(status, F_data_not); + } + + { + size_t length = 0; + f_socket_t socket = f_socket_t_initialize; + socket.size_write = 0; + + const f_status_t status = f_socket_write_stream(&socket, 0, (void *) buffer, &length); + + assert_int_equal(status, F_data_not); + } +} + void test__f_socket_write_stream__works(void **state) { f_socket_t socket = f_socket_t_initialize; diff --git a/level_0/f_socket/tests/unit/c/test-socket-write_stream.h b/level_0/f_socket/tests/unit/c/test-socket-write_stream.h index 5bc28e52f..414146de6 100644 --- a/level_0/f_socket/tests/unit/c/test-socket-write_stream.h +++ b/level_0/f_socket/tests/unit/c/test-socket-write_stream.h @@ -24,6 +24,13 @@ extern void test__f_socket_write_stream__fails(void **state); */ extern void test__f_socket_write_stream__parameter_checking(void **state); +/** + * Test that the function returns F_data_not. + * + * @see f_socket_write_stream() + */ +extern void test__f_socket_write_stream__returns_data_not(void **state); + /** * Test that function works. * diff --git a/level_0/f_socket/tests/unit/c/test-socket.c b/level_0/f_socket/tests/unit/c/test-socket.c index e521eac37..368682bfa 100644 --- a/level_0/f_socket/tests/unit/c/test-socket.c +++ b/level_0/f_socket/tests/unit/c/test-socket.c @@ -63,21 +63,27 @@ int main(void) { cmocka_unit_test(test__f_socket_option_set__works), cmocka_unit_test(test__f_socket_read__fails), + cmocka_unit_test(test__f_socket_read__returns_data_not), cmocka_unit_test(test__f_socket_read__works), cmocka_unit_test(test__f_socket_read_message__fails), + cmocka_unit_test(test__f_socket_read_message__returns_data_not), cmocka_unit_test(test__f_socket_read_message__works), cmocka_unit_test(test__f_socket_read_stream__fails), + cmocka_unit_test(test__f_socket_read_stream__returns_data_not), cmocka_unit_test(test__f_socket_read_stream__works), cmocka_unit_test(test__f_socket_write__fails), + cmocka_unit_test(test__f_socket_write__returns_data_not), cmocka_unit_test(test__f_socket_write__works), cmocka_unit_test(test__f_socket_write_message__fails), + cmocka_unit_test(test__f_socket_write_message__returns_data_not), cmocka_unit_test(test__f_socket_write_message__works), cmocka_unit_test(test__f_socket_write_stream__fails), + cmocka_unit_test(test__f_socket_write_stream__returns_data_not), cmocka_unit_test(test__f_socket_write_stream__works), cmocka_unit_test(test__f_socket_addressss_destroy_callback__fails),