Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

netsocket: socket operations return error codes via return values #4092

Merged

Conversation

ManManson
Copy link
Member

Switch to returning socket error codes explicitly via return values instead of using legacy functions getSockErr(), setSockErr, strSockError() to get extended error context.

To facilitate that, use tl::expected<T, std::error_code> as the return value type for all main socket operations: read, write, open, listen.

Moving to this new approach has numerous benefits over the old one:

  1. Instead of using POSIX constants directly, we wrap them into std::error_code instances, which allows to attach custom error categories to them. This can be used to customize error messages and error codes mapping to platform-independent std::error_conditions.

  2. Calling separate get/setSockErr() functions is error-prone: one can easily forget to check the error condition from getSockErr() and the value will be overwritten by the next socket function without the ability to recover the former error.

    Conversely, one can forget to call setSockErr() to set the proper error code for the caller to check upon.

  3. As mentioned above, std::error_code:s can be implicitly mapped to platform-independent std::error_conditions, allowing for this code to compile successfuly:

        if (errCode == std::errc::connection_reset) { ... }

    This allows for very convenient and portable error checking code, which completely hides implementation details of how a particular error code is implemented (but, if one really needs to, they still can extract the platform-dependent error code value to get the extended error context).

The getSockErr(), setSockErr and strSockError() functions are still used in the netsocket.cpp implementation, but now they are strictly confined to this particular translation unit, meaning they have now become an implementation detail, rather than a part of public API contract of netplay library.

Signed-off-by: Pavel Solodovnikov [email protected]

…ketSet()`

This instead should always throw `std::bad_alloc`.

Signed-off-by: Pavel Solodovnikov <[email protected]>
`operator new` will throw a `std::bad_alloc` exception
instead of returning `nullptr`, so there's no need
to check for `nullptr` after trying to allocate a new
`Socket` instance.

Signed-off-by: Pavel Solodovnikov <[email protected]>
Signed-off-by: Pavel Solodovnikov <[email protected]>
…slation of network errors

Signed-off-by: Pavel Solodovnikov <[email protected]>
…, std::error_code>`

Plus, add the necessary dependency for the `netplay` library
in order for it to find `tl::expected` header files.

Signed-off-by: Pavel Solodovnikov <[email protected]>
Switch to returning socket error codes explicitly via return values
instead of using legacy functions `getSockErr()`, `setSockErr`,
`strSockError()` to get extended error context.

To facilitate that, use `tl::expected<T, std::error_code>` as the
return value type for all main socket operations: read, write, open,
listen.

Moving to this new approach has numerous benefits over the old one:

1. Instead of using POSIX constants directly, we wrap them into
   `std::error_code` instances, which allows to attach custom error
   categories to them. This can be used to customize error messages
   and error codes mapping to platform-independent
   `std::error_conditions`.
2. Calling separate `get/setSockErr()` functions is error-prone:
   one can easily forget to check the error condition from
   `getSockErr()` and the value will be overwritten by the next
   socket function without the ability to recover the former error.
   Conversely, one can forget to call `setSockErr()` to set
   the proper error code for the caller to check upon.
3. As mentioned above, `std::error_code:s` can be implicitly mapped
   to platform-independent `std::error_conditions`, allowing for this
   code to compile successfuly:

	if (errCode == std::errc::connection_reset) { ... }

   This allows for very convenient and portable error checking
   code, which completely hides implementation details of how
   a particular error code is implemented (but, if one really needs to,
   they still can extract the platform-dependent error code value
   to get the extended error context).

The `getSockErr()`, `setSockErr` and `strSockError()` functions
are still used in the `netsocket.cpp` implementation, but now they are
strictly confined to this particular translation unit, meaning
they have now become an implementation detail, rather than a part of
public API contract of `netplay` library.

Signed-off-by: Pavel Solodovnikov <[email protected]>
@ManManson ManManson force-pushed the netsocket_api_expected_refactoring branch from 95c25c2 to 6337be0 Compare October 13, 2024 11:20
@past-due past-due merged commit d0296f1 into Warzone2100:master Oct 19, 2024
37 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants