⚠ This page is served via a proxy. Original site: https://github.com
This service does not collect credentials or authentication data.
Skip to content

Conversation

@sgerbino
Copy link
Collaborator

@sgerbino sgerbino commented Jan 26, 2026

Add a cross-platform socket options API using simple named getter/setter methods. This approach was chosen over the Asio-style template-based API for better discoverability and simplicity.

New socket methods:

  • set_no_delay(bool) / no_delay() - TCP_NODELAY (disable Nagle's algorithm)
  • set_keep_alive(bool) / keep_alive() - SO_KEEPALIVE
  • set_receive_buffer_size(int) / receive_buffer_size() - SO_RCVBUF
  • set_send_buffer_size(int) / send_buffer_size() - SO_SNDBUF
  • set_linger(bool, int) / linger() - SO_LINGER

Resolves #73.

Summary by CodeRabbit

  • New Features

    • Adds a comprehensive socket options API to configure TCP behavior (no-delay, keep-alive), receive/send buffer sizes, and linger settings.
    • Introduces a public linger options type for finer control over connection termination.
  • Bug Fixes

    • Replaces debug-time assertions with runtime error handling and defensive null-checks when socket or acceptor backends are uninitialized.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 26, 2026

📝 Walkthrough

Walkthrough

Adds a cross-platform socket options API (set/get for TCP_NODELAY, SO_KEEPALIVE, SO_RCVBUF, SO_SNDBUF, SO_LINGER), introduces per-operation cancellation paths in epoll, and replaces assert() checks with runtime guards or logic_error throws in socket/acceptor code.

Changes

Cohort / File(s) Summary
Public headers
include/boost/corosio/socket.hpp, include/boost/corosio/acceptor.hpp
Added linger_options and declarations for new socket option methods; replaced some assert() usages with runtime logic_error/guards; removed <cassert>.
Core socket implementation
src/corosio/src/socket.cpp
Implemented socket option public methods (set/no_delay, keep_alive, recv/send buffer sizes, linger) with impl_ checks and error propagation; replaced assert in cancel() with null-check.
Acceptor implementation
src/corosio/src/acceptor.cpp
Replaced assert() in cancel() with early-return guard; removed <cassert>.
epoll backend (Linux)
src/corosio/src/detail/epoll/sockets.hpp, src/corosio/src/detail/epoll/sockets.cpp
Added socket option implementations using getsockopt/setsockopt (TCP_NODELAY, SO_KEEPALIVE, SO_RCVBUF, SO_SNDBUF, SO_LINGER); added per-op cancellation helpers and expanded cancel flow.
iocp backend (Windows)
src/corosio/src/detail/iocp/sockets.hpp
Declared corresponding socket option overrides for Windows win_socket_impl (setsockopt/getsockopt + error mapping).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Socket as boost::corosio::socket
    participant Impl as socket_impl (epoll/iocp)
    participant OS as OS Socket

    User->>Socket: set_no_delay(true)
    Socket->>Socket: validate impl_ (throw if null)
    Socket->>Impl: set_no_delay(true)
    Impl->>OS: setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,...)
    OS-->>Impl: result / errno
    Impl-->>Socket: system::error_code
    Socket-->>User: throw on error / return

    User->>Socket: cancel()
    Socket->>Socket: validate impl_ (return if null)
    Socket->>Impl: cancel()
    Impl->>Impl: cancel_single_op(rd/wr/conn) / unregister / post completions
    Impl-->>Socket: cancellations posted
    Socket-->>User: cancel complete
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • vinniefalco

Poem

🐰
I hopped through headers, flags, and streams,
Turning asserts into safer dreams,
Nagle skipped, buffers stretched wide,
Linger set for the graceful tide,
Hooray — cross-platform sockets stride!

🚥 Pre-merge checks | ✅ 2 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR implements named methods for socket options (Option A from issue #73), covering TCP_NODELAY, SO_KEEPALIVE, SO_RCVBUF, SO_SNDBUF, and SO_LINGER. However, SO_REUSEADDR and Linux-specific keepalive options are not included, and the Asio-style template-based set_option/get_option methods (also listed in acceptance criteria) are not provided. Consider implementing SO_REUSEADDR option and either the Asio-style set_option/get_option template methods or clarify why Option B was deferred.
Out of Scope Changes check ❓ Inconclusive The PR includes changes to error handling (replacing assertions with runtime exceptions) and expanding cancellation support in epoll implementation, which are aligned with improving robustness but were not explicitly stated in issue #73 objectives. Clarify whether assertion-to-exception conversions and enhanced cancellation handling are intentional scope additions or necessary supporting changes for the socket options feature.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: implementing a socket options API using named getter/setter methods.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

@cppalliance-bot
Copy link

cppalliance-bot commented Jan 26, 2026

An automated preview of the documentation is available at https://79.corosio.prtest3.cppalliance.org/index.html

If more commits are pushed to the pull request, the docs will rebuild at the same URL.

2026-01-26 14:53:15 UTC

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
include/boost/corosio/socket.hpp (1)

89-123: Document linger_options members explicitly.
This public type is part of the API surface, but the doc doesn’t describe the member semantics or when timeout is used. Add brief member descriptions (units and when ignored) to make the contract clear.

✏️ Suggested doc update
-    /** Options for SO_LINGER socket option. */
+    /** Options for SO_LINGER socket option.
+        `@par` Members
+        - enabled: Whether SO_LINGER is enabled.
+        - timeout: Linger timeout in seconds (ignored when enabled is false).
+    */
As per coding guidelines.
include/boost/corosio/acceptor.hpp (1)

220-256: Document accept() throwing when not listening.
The implementation now throws std::logic_error if impl_ is null; please surface that in the API docs.

✏️ Suggested doc update
@@
         `@par` Preconditions
         The acceptor must be listening (`is_open() == true`).
         The peer socket must be associated with the same execution context.
+        `@throws` std::logic_error if the acceptor is not listening.
As per coding guidelines.
🤖 Fix all issues with AI agents
In `@include/boost/corosio/socket.hpp`:
- Around line 300-304: Update the documentation for the member function
connect(endpoint ep) to explicitly state it can throw std::logic_error when the
socket is not open (i.e., when impl_ is null); reference the connect(endpoint)
function and its early check of impl_ which calls detail::throw_logic_error, and
keep the existing async error notes for connect_awaitable intact.
- Around line 374-467: The documented socket option accessors (set_no_delay,
no_delay, set_keep_alive, keep_alive, set_receive_buffer_size,
receive_buffer_size, set_send_buffer_size, send_buffer_size, set_linger, linger)
currently only mention std::system_error; update their doc comments to include a
precondition that the socket must be open and a throws note that
std::logic_error is thrown when the socket is closed (either add the brief
"Precondition: socket must be open" and "Throws: std::logic_error if the socket
is closed" to each method's comment, or add a single section-wide note at the
top of this options block stating the same so individual methods don’t need
repetition). Ensure the wording matches existing style and appears alongside the
existing `@throws` std::system_error entries.

@sgerbino sgerbino force-pushed the feature/socket-options branch from db9345c to 70717b5 Compare January 26, 2026 14:14
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/corosio/src/detail/epoll/sockets.cpp (1)

10-26: Add the required implementation overview block after includes.

This file is non-trivial and should have a /* */ overview right after includes.
As per coding guidelines.

📝 Suggested overview block
 `#include` <sys/socket.h>
 `#include` <unistd.h>

+/*
+    epoll Socket Options Implementation
+    ----------------------------------
+    Provides setsockopt/getsockopt wrappers for common options and integrates
+    with epoll_socket_impl cancellation semantics.
+*/
♻️ Duplicate comments (2)
include/boost/corosio/socket.hpp (2)

262-295: Document connect() throwing when the socket is closed.

The runtime check now throws std::logic_error when the socket isn’t open, but the doc only lists async error codes.
As per coding guidelines.


366-459: Add open-socket precondition/std::logic_error to option docs.

All option accessors throw std::logic_error on a closed socket, but docs only mention std::system_error. Add a section-wide precondition/throws note or per-method notes.
As per coding guidelines.

Add a cross-platform socket options API using simple named getter/setter
methods. This approach was chosen over the Asio-style template-based API
for better discoverability and simplicity.

New socket methods:
- set_no_delay(bool) / no_delay() - TCP_NODELAY (disable Nagle's algorithm)
- set_keep_alive(bool) / keep_alive() - SO_KEEPALIVE
- set_receive_buffer_size(int) / receive_buffer_size() - SO_RCVBUF
- set_send_buffer_size(int) / send_buffer_size() - SO_SNDBUF
- set_linger(bool, int) / linger() - SO_LINGER

Changes:
- include/boost/corosio/socket.hpp: Add linger_options struct, virtual
  methods to socket_impl, and public methods to socket class
- src/corosio/src/socket.cpp: Implement socket option methods with error
  handling
- src/corosio/src/detail/epoll/sockets.hpp: Declare option methods for
  epoll_socket_impl
- src/corosio/src/detail/epoll/sockets.cpp: Implement POSIX setsockopt/
  getsockopt calls, add netinet/tcp.h include
- src/corosio/src/detail/iocp/sockets.hpp: Implement Windows setsockopt/
  getsockopt calls inline in win_socket_impl
- bench/corosio/socket_latency_bench.cpp: Replace manual setsockopt
  workaround with new set_no_delay() API
- test/unit/socket.cpp: Add unit tests for all socket options
@sgerbino sgerbino force-pushed the feature/socket-options branch from 70717b5 to fbe79e4 Compare January 26, 2026 14:46
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@include/boost/corosio/socket.hpp`:
- Around line 85-90: Document the linger_options struct and its members by
adding doc comments for the type and each field: describe what linger_options
configures (SO_LINGER behavior), document enabled as a boolean that turns linger
on/off, and document timeout as the linger interval in seconds (units: seconds),
acceptable range/constraints (non-negative integer, typically >= 0), and default
values (enabled=false, timeout=0); update the public header comments adjacent to
linger_options, enabled, and timeout so the API docs clearly state semantics and
constraints.
- Around line 451-462: The docstring for set_linger currently omits the valid
range for the timeout parameter; update the comment for set_linger(bool enabled,
int timeout) to state that timeout is specified in seconds and must be
non‑negative (timeout >= 0), since negative values are rejected (EINVAL) by the
implementation; also mention that this controls the SO_LINGER option behavior
when enabled and that callers must pass a non‑negative timeout to avoid errors.

In `@src/corosio/src/detail/epoll/sockets.cpp`:
- Around line 20-23: Add a /* ... */ implementation-overview comment block
immediately after the includes in src/corosio/src/detail/epoll/sockets.cpp that
summarizes the file’s main flow and tricky areas: describe how the epoll loop is
structured (use of epoll_ctl/epoll_wait), how socket lifecycle and ownership are
managed, cancellation/shutdown semantics, and relevant socket option handling
(e.g., TCP_NODELAY, SO_REUSEADDR) so reviewers can quickly understand functions
in this file (the epoll handling code and any socket helper routines).

Comment on lines +85 to +90
/** Options for SO_LINGER socket option. */
struct linger_options
{
bool enabled = false;
int timeout = 0; // seconds
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Document linger_options members in the public header.

As a public API type, the fields should be documented (meaning, units, constraints) to meet the docstring requirements. As per coding guidelines.

📝 Suggested doc update
-    /** Options for SO_LINGER socket option. */
+    /** Options for SO_LINGER socket option.
+
+        `@par` Members
+        - `enabled`: Whether SO_LINGER is enabled.
+        - `timeout`: Linger timeout in seconds (non-negative).
+    */
     struct linger_options
     {
         bool enabled = false;
         int timeout = 0;  // seconds
     };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/** Options for SO_LINGER socket option. */
struct linger_options
{
bool enabled = false;
int timeout = 0; // seconds
};
/** Options for SO_LINGER socket option.
`@par` Members
- `enabled`: Whether SO_LINGER is enabled.
- `timeout`: Linger timeout in seconds (non-negative).
*/
struct linger_options
{
bool enabled = false;
int timeout = 0; // seconds
};
🤖 Prompt for AI Agents
In `@include/boost/corosio/socket.hpp` around lines 85 - 90, Document the
linger_options struct and its members by adding doc comments for the type and
each field: describe what linger_options configures (SO_LINGER behavior),
document enabled as a boolean that turns linger on/off, and document timeout as
the linger interval in seconds (units: seconds), acceptable range/constraints
(non-negative integer, typically >= 0), and default values (enabled=false,
timeout=0); update the public header comments adjacent to linger_options,
enabled, and timeout so the API docs clearly state semantics and constraints.

Comment on lines +451 to +462
/** Set the SO_LINGER option.
Controls behavior when closing a socket with unsent data.
@param enabled If `true`, close() will block until data is sent
or the timeout expires. If `false`, close() returns immediately.
@param timeout The linger timeout in seconds (only used if enabled).
@throws std::logic_error if the socket is not open.
@throws std::system_error on failure.
*/
void set_linger(bool enabled, int timeout);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Clarify the valid range for timeout in set_linger().

The implementation rejects negative values (EINVAL). Document the precondition to avoid surprises for callers. As per coding guidelines.

📝 Suggested doc tweak
-        `@param` timeout The linger timeout in seconds (only used if enabled).
+        `@param` timeout The linger timeout in seconds (only used if enabled).
+            Must be non-negative.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/** Set the SO_LINGER option.
Controls behavior when closing a socket with unsent data.
@param enabled If `true`, close() will block until data is sent
or the timeout expires. If `false`, close() returns immediately.
@param timeout The linger timeout in seconds (only used if enabled).
@throws std::logic_error if the socket is not open.
@throws std::system_error on failure.
*/
void set_linger(bool enabled, int timeout);
/** Set the SO_LINGER option.
Controls behavior when closing a socket with unsent data.
`@param` enabled If `true`, close() will block until data is sent
or the timeout expires. If `false`, close() returns immediately.
`@param` timeout The linger timeout in seconds (only used if enabled).
Must be non-negative.
`@throws` std::logic_error if the socket is not open.
`@throws` std::system_error on failure.
*/
void set_linger(bool enabled, int timeout);
🤖 Prompt for AI Agents
In `@include/boost/corosio/socket.hpp` around lines 451 - 462, The docstring for
set_linger currently omits the valid range for the timeout parameter; update the
comment for set_linger(bool enabled, int timeout) to state that timeout is
specified in seconds and must be non‑negative (timeout >= 0), since negative
values are rejected (EINVAL) by the implementation; also mention that this
controls the SO_LINGER option behavior when enabled and that callers must pass a
non‑negative timeout to avoid errors.

Comment on lines 20 to 23
#include <errno.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/epoll.h>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add the required implementation overview block after includes.

This file contains non-trivial logic; please add a /* */ overview comment after the includes to summarize the main flow and tricky parts (cancellation, lifetime, socket options). As per coding guidelines.

📝 Suggested placement
 `#include` <sys/socket.h>
 `#include` <unistd.h>
 
+/*
+    epoll socket implementation overview
+    - Non-blocking syscalls with one-shot epoll registration.
+    - Cancellation unregisters and posts completion while preserving impl lifetime.
+    - Socket option helpers wrap getsockopt/setsockopt with error_code.
+*/
+
 namespace boost {
 namespace corosio {
 namespace detail {
🤖 Prompt for AI Agents
In `@src/corosio/src/detail/epoll/sockets.cpp` around lines 20 - 23, Add a /* ...
*/ implementation-overview comment block immediately after the includes in
src/corosio/src/detail/epoll/sockets.cpp that summarizes the file’s main flow
and tricky areas: describe how the epoll loop is structured (use of
epoll_ctl/epoll_wait), how socket lifecycle and ownership are managed,
cancellation/shutdown semantics, and relevant socket option handling (e.g.,
TCP_NODELAY, SO_REUSEADDR) so reviewers can quickly understand functions in this
file (the epoll handling code and any socket helper routines).

@sgerbino sgerbino merged commit 786d3cd into cppalliance:develop Jan 26, 2026
26 of 27 checks passed
@sgerbino sgerbino deleted the feature/socket-options branch January 26, 2026 15:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement socket options API

2 participants