Skip to content

refactor(websocket): migrate TCP receive path to std::span and update protocol API#323

Merged
kcenon merged 4 commits into
mainfrom
feature/318-websocket-span-migration
Dec 18, 2025
Merged

refactor(websocket): migrate TCP receive path to std::span and update protocol API#323
kcenon merged 4 commits into
mainfrom
feature/318-websocket-span-migration

Conversation

@kcenon

@kcenon kcenon commented Dec 18, 2025

Copy link
Copy Markdown
Owner

Summary

  • Migrate WebSocket receive path to use std::span<const uint8_t> callbacks
  • Update websocket_protocol::process_data() to accept span instead of vector
  • Update websocket_socket to use tcp_socket::set_receive_callback_view() for zero-copy TCP-to-WebSocket data flow

Changes

websocket_protocol

  • process_data(const std::vector<uint8_t>&)process_data(std::span<const uint8_t>)
  • Added <span> header include

websocket_socket

  • Use set_receive_callback_view() instead of set_receive_callback() for all TCP receive callbacks
  • on_tcp_receive(const std::vector<uint8_t>&)on_tcp_receive(std::span<const uint8_t>)
  • Updated handshake callbacks to use span-based receive

Performance Impact

  • Eliminates per-read std::vector allocation solely for TCP-to-protocol handoff
  • Data is copied once into the protocol's internal buffer for frame processing
  • No per-read heap allocation required when span callback is used

Test Plan

  • All WebSocketProtocol unit tests pass (24/24)
  • Build succeeds with -DNETWORK_BUILD_TESTS=ON
  • No new compiler warnings

Related Issues

… protocol API

- Update websocket_protocol::process_data() to accept std::span<const uint8_t>
  instead of const std::vector<uint8_t>&
- Update websocket_socket to use tcp_socket::set_receive_callback_view() for
  zero-copy TCP-to-WebSocket data flow
- Change on_tcp_receive() to accept std::span<const uint8_t>
- Update all handshake callbacks to use span-based receive

This eliminates per-read std::vector allocation solely for TCP-to-protocol
handoff. Data is copied once into the protocol's internal buffer for frame
processing.

Part of Epic #315 (TCP receive zero-allocation hot path)
Closes #318
Document the WebSocket receive path migration to std::span callback:
- websocket_protocol::process_data() API change
- websocket_socket using tcp_socket::set_receive_callback_view()
- Performance improvement details

Part of Epic #315, #318
@github-actions

Copy link
Copy Markdown
Contributor

Performance Comparison

Base Branch Results

No base results

PR Branch Results

No PR results

Add is_open() check in do_read() to prevent UBSAN errors from accessing
null descriptor_state when the socket has already been closed.

This fixes BoundaryTest.HandlesSingleByteMessage failure under
undefined behavior sanitizer.
@github-actions

Copy link
Copy Markdown
Contributor

Performance Comparison

Base Branch Results

No base results

PR Branch Results

No PR results

Document the socket validity check fix in all changelog files:
- Added is_open() check before async_read_some() in tcp_socket::do_read()
- Prevents null descriptor_state access when socket is already closed
- Fixes BoundaryTest.HandlesSingleByteMessage UBSAN failure
@github-actions

Copy link
Copy Markdown
Contributor

Performance Comparison

Base Branch Results

No base results

PR Branch Results

No PR results

@kcenon kcenon merged commit 199d95b into main Dec 18, 2025
44 checks passed
@kcenon kcenon deleted the feature/318-websocket-span-migration branch December 18, 2025 17:45
kcenon added a commit that referenced this pull request Apr 13, 2026
… protocol API (#323)

* refactor(websocket): migrate TCP receive path to std::span and update protocol API

- Update websocket_protocol::process_data() to accept std::span<const uint8_t>
  instead of const std::vector<uint8_t>&
- Update websocket_socket to use tcp_socket::set_receive_callback_view() for
  zero-copy TCP-to-WebSocket data flow
- Change on_tcp_receive() to accept std::span<const uint8_t>
- Update all handshake callbacks to use span-based receive

This eliminates per-read std::vector allocation solely for TCP-to-protocol
handoff. Data is copied once into the protocol's internal buffer for frame
processing.

Part of Epic #315 (TCP receive zero-allocation hot path)
Closes #318

* docs: add WebSocket zero-copy receive path to changelogs

Document the WebSocket receive path migration to std::span callback:
- websocket_protocol::process_data() API change
- websocket_socket using tcp_socket::set_receive_callback_view()
- Performance improvement details

Part of Epic #315, #318

* fix(tcp_socket): add socket validity check before async read operation

Add is_open() check in do_read() to prevent UBSAN errors from accessing
null descriptor_state when the socket has already been closed.

This fixes BoundaryTest.HandlesSingleByteMessage failure under
undefined behavior sanitizer.

* docs: add tcp_socket UBSAN fix to changelogs

Document the socket validity check fix in all changelog files:
- Added is_open() check before async_read_some() in tcp_socket::do_read()
- Prevents null descriptor_state access when socket is already closed
- Fixes BoundaryTest.HandlesSingleByteMessage UBSAN failure
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.

refactor(websocket): migrate TCP receive path to std::span and update protocol API

1 participant