Skip to content

feat(socket): Socket::set_dscp()/get_dscp() typed option setters - #736

Merged
finger563 merged 3 commits into
mainfrom
feat/socket-set-dscp
Aug 24, 2026
Merged

feat(socket): Socket::set_dscp()/get_dscp() typed option setters#736
finger563 merged 3 commits into
mainfrom
feat/socket-set-dscp

Conversation

@finger563

Copy link
Copy Markdown
Contributor

Description

Follow-up to #735: the SocketReactor was reaching for the raw native handle and calling ::setsockopt directly to apply a DSCP marking. This moves that onto the socket itself, alongside the existing typed option setters (set_receive_timeout, set_receive_buffer_size, set_reuse_address, …), so callers never need the native handle or platform #ifdefs for this.

espp::Socket

  • set_dscp(espp::Dscp) — applies IP_TOS via the existing set_option() wrapper (DSCP in the upper 6 bits, RFC 2474). Best-effort, documented as network/driver treatment only. Out-of-range (static_cast'd) code points are rejected with a log rather than silently masked to a different code point.
  • get_dscp() — reads the code point back from IP_TOS (ECN bits discarded), following the get_receive_buffer_size() pattern.

espp::SocketReactor

add_udp_receiver() now just calls socket.set_dscp(...) — the raw setsockopt block is gone.

Python

  • set_dscp/get_dscp bound on Socket.
  • Fixes a pre-existing binding gap: UdpSocket/TcpSocket were bound without declaring espp::Socket as their base, so no base Socket method (set_receive_timeout, native_handle, …) was reachable from Python. They now declare the base (preserved across regeneration via a new _fix_base_classes postprocess in autogenerate_bindings.py), and the stub declares the inheritance too.

Testing

  • pc/tests/socket_reactor.cpp: read-back checks now dogfood get_dscp(), plus a direct set_dscp/get_dscp round-trip including out-of-range rejection leaving the previous code point in place — 49/49, repeated runs.
  • Python smoke-tested end-to-end: set_dscp/get_dscp on both UdpSocket and TcpSocket, inherited base methods (set_receive_timeout) now reachable, __mro__ shows Socket as base.
  • esp32 socket example builds; lib/pybind builds; cppcheck clean.

🤖 Generated with Claude Code

The SocketReactor was reaching for the raw native handle and calling
::setsockopt directly to apply a DSCP marking. Move that onto the socket
itself, alongside the existing typed option setters:

- Socket::set_dscp(espp::Dscp): applies IP_TOS via the existing set_option()
  wrapper; rejects out-of-range (static_cast'd) code points with a log rather
  than silently masking them.
- Socket::get_dscp(): reads the code point back from IP_TOS (ECN bits
  discarded), following the get_receive_buffer_size() pattern.
- SocketReactor::add_udp_receiver now just calls socket.set_dscp() - no
  native handle, no platform ifdefs.
- pc test dogfoods the new getter for the read-back checks and adds a direct
  set/get round-trip incl. rejection leaving the previous value in place
  (socket_reactor suite 49/49).
- python: set_dscp/get_dscp bound on Socket; UdpSocket/TcpSocket bindings now
  declare Socket as their base (pre-existing gap - no base Socket method was
  reachable from python subclass instances), preserved on regeneration via a
  new _fix_base_classes postprocess in autogenerate_bindings.py; stub updated
  (TcpSocket/UdpSocket now inherit Socket).
- docs: socket README lists the typed option setters.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 24, 2026 14:59
@github-actions

Copy link
Copy Markdown

✅Static analysis result - no issues found! ✅

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR moves DSCP (DiffServ) marking into the espp::Socket API via typed set_dscp(espp::Dscp) / get_dscp() helpers, updates SocketReactor to use the new API instead of raw setsockopt, and wires the functionality through the Python bindings (including fixing missing base-class inheritance for UdpSocket/TcpSocket in Python).

Changes:

  • Add Socket::set_dscp() / Socket::get_dscp() implemented via IP_TOS and the existing set_option() wrapper.
  • Update SocketReactor::add_udp_receiver() to call socket.set_dscp(...) and update host tests to use get_dscp() and validate out-of-range rejection behavior.
  • Expose DSCP APIs in Python and fix Python inheritance so derived sockets inherit base Socket methods.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
components/socket/include/socket.hpp Adds public typed DSCP setter/getter declarations and includes dscp.hpp.
components/socket/src/socket.cpp Implements DSCP set/get using IP_TOS, with out-of-range rejection.
components/socket/src/socket_reactor.cpp Replaces direct setsockopt(IP_TOS) with Socket::set_dscp() usage.
components/socket/README.md Documents the typed option setters including DSCP helpers.
pc/tests/socket_reactor.cpp Updates DSCP verification to use get_dscp() and adds round-trip/rejection tests.
lib/python_bindings/pybind_espp.cpp Binds set_dscp/get_dscp and fixes pybind base classes for TcpSocket/UdpSocket.
lib/python_bindings/espp/__init__.pyi Updates stubs to include DSCP APIs and correct Python inheritance.
lib/autogenerate_bindings.py Adds a postprocess pass to enforce socket base classes in generated pybind code.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread lib/autogenerate_bindings.py
…g cleanly

_fix_base_classes() now counts occurrences like _fix_implicit_default_ctors
and prints a loud warning when a pattern applies != 1 time, so a litgen
output drift cannot silently regress python-side UdpSocket/TcpSocket
inheritance on regeneration.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comment thread lib/autogenerate_bindings.py
…eserves stub fixes

autogenerate() overwrites espp/__init__.pyi but only postprocessed
pybind_espp.cpp, so a regeneration would have reverted the committed
TcpSocket(Socket)/UdpSocket(Socket) stub inheritance. Add
_postprocess_generated_stub() with the equivalent base-class replacements
(same exactly-once count check + loud warning as _fix_base_classes) and
apply it to the generated stub; the _STUB_FIX map is the extension point
for future developer-facing .pyi improvements.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@finger563
finger563 merged commit 824f208 into main Aug 24, 2026
150 checks passed
@finger563
finger563 deleted the feat/socket-set-dscp branch August 24, 2026 16:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request socket

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants