Skip to content

server: SdStateHandle trait + drop Arc<SdStateManager> requirement#105

Draft
JustinKovacich wants to merge 1 commit into
feature/phase20a_server_recv_buf_splitfrom
feature/phase20b_sd_state_handle
Draft

server: SdStateHandle trait + drop Arc<SdStateManager> requirement#105
JustinKovacich wants to merge 1 commit into
feature/phase20a_server_recv_buf_splitfrom
feature/phase20b_sd_state_handle

Conversation

@JustinKovacich
Copy link
Copy Markdown
Contributor

Adds SdStateHandle + WrappableSdStateHandle traits in src/server/sd_state.rs and threads them through Server as a new Hsd type parameter (default Arc<SdStateManager>). Mirrors the pattern established by 19f's SocketHandle /
WrappableSocketHandle. Same shape, same Send/Sync defaults (neither bound at trait level — caller adds at use sites).

Two impls ship:

  • Arc<SdStateManager>: SdStateHandle + WrappableSdStateHandle (the existing default; preserves std-side behavior).
  • &'static SdStateManager: SdStateHandle (no-alloc; user declares static SD_STATE: SdStateManager = SdStateManager::new(); and supplies &SD_STATE via a future Server::new_with_handles constructor).

SdStateManager itself becomes pub and SdStateManager::new() becomes pub const fn so the static-storage pattern compiles. The internal methods (next_session_id_with_reboot_flag, reboot_flag, send_offer_service) stay pub(super) — consumers shouldn't call them directly; they go through Server.

Server's existing new_with_deps / new_passive_with_deps constructors require Hsd: WrappableSdStateHandle because they build the manager internally via SdStateManager::new() then Hsd::wrap(...). The future Server::new_with_handles will take Hsd: SdStateHandle directly (no wrap step), enabling the no-alloc path with &'static SdStateManager.

announcement_loop's method-level where clause picks up the new Hsd: Send + Sync bound, mirroring the existing H: Send + Sync and F: Send + Sync bounds. The _local variant has no such requirement and works for any Hsd: SdStateHandle.

Type-signature width: Server now reads Server<R, S, F, Tm, H = Arc<F::Socket>, Hsd = Arc<SdStateManager>>. Both defaults preserve every existing call site — Server<R, S, F, Tm> and Server<R, S, F, Tm, Arc<SomeSocket>> both still resolve correctly. No churn in tests/ or examples/.

Clears 20-pre alloc audit's category-E.2 finding. Combined with the 4f9d36e recv-buffer split, two of the four "no-alloc Server" remediation items are done.

What this leaves:

  • E.1: Arc<EventPublisher<R, S, H>> field on Server. Same shape via an EventPublisherHandle trait — next branch.
  • D: Server::new_with_handles constructor that takes pre-built H + Hsd (and the future Hep for E.1) directly, skipping the wrap step. Lands after E.1 so the constructor's parameter list is final.

Gates green:

  • cargo fmt --check
  • cargo clippy --tests (2 pre-existing warnings, unrelated)
  • cargo build --workspace --all-targets
  • cargo build --no-default-features --features client,server,bare_metal
  • cargo build -p simple-someip-embassy-net --target thumbv7em-none-eabihf
  • cargo test --features client-tokio,server-tokio --test client_server -- --test-threads=1 (11/11)
  • cargo test --features client,server,bare_metal --test bare_metal_e2e (2/2)
  • cargo test -p simple-someip-embassy-net --test loopback (3/3)

Adds `SdStateHandle` + `WrappableSdStateHandle` traits in
`src/server/sd_state.rs` and threads them through `Server` as a
new `Hsd` type parameter (default `Arc<SdStateManager>`). Mirrors
the pattern established by 19f's `SocketHandle` /
`WrappableSocketHandle`. Same shape, same Send/Sync defaults
(neither bound at trait level — caller adds at use sites).

Two impls ship:
- `Arc<SdStateManager>: SdStateHandle + WrappableSdStateHandle`
  (the existing default; preserves std-side behavior).
- `&'static SdStateManager: SdStateHandle` (no-alloc; user
  declares `static SD_STATE: SdStateManager = SdStateManager::new();`
  and supplies `&SD_STATE` via a future `Server::new_with_handles`
  constructor).

`SdStateManager` itself becomes `pub` and `SdStateManager::new()`
becomes `pub const fn` so the static-storage pattern compiles.
The internal methods (`next_session_id_with_reboot_flag`,
`reboot_flag`, `send_offer_service`) stay `pub(super)` —
consumers shouldn't call them directly; they go through Server.

Server's existing `new_with_deps` / `new_passive_with_deps`
constructors require `Hsd: WrappableSdStateHandle` because they
build the manager internally via `SdStateManager::new()` then
`Hsd::wrap(...)`. The future `Server::new_with_handles` will
take `Hsd: SdStateHandle` directly (no `wrap` step), enabling
the no-alloc path with `&'static SdStateManager`.

`announcement_loop`'s method-level `where` clause picks up the
new `Hsd: Send + Sync` bound, mirroring the existing `H: Send +
Sync` and `F: Send + Sync` bounds. The `_local` variant has no
such requirement and works for any `Hsd: SdStateHandle`.

Type-signature width: Server now reads `Server<R, S, F, Tm,
H = Arc<F::Socket>, Hsd = Arc<SdStateManager>>`. Both
defaults preserve every existing call site — `Server<R, S, F, Tm>`
and `Server<R, S, F, Tm, Arc<SomeSocket>>` both still resolve
correctly. No churn in `tests/` or `examples/`.

Clears 20-pre alloc audit's category-E.2 finding. Combined with
the 4f9d36e recv-buffer split, two of the four "no-alloc Server"
remediation items are done.

What this leaves:
- E.1: `Arc<EventPublisher<R, S, H>>` field on Server. Same
  shape via an `EventPublisherHandle` trait — next branch.
- D: `Server::new_with_handles` constructor that takes pre-built
  `H` + `Hsd` (and the future `Hep` for E.1) directly, skipping
  the `wrap` step. Lands after E.1 so the constructor's
  parameter list is final.

Gates green:
- cargo fmt --check
- cargo clippy --tests (2 pre-existing warnings, unrelated)
- cargo build --workspace --all-targets
- cargo build --no-default-features --features client,server,bare_metal
- cargo build -p simple-someip-embassy-net --target thumbv7em-none-eabihf
- cargo test --features client-tokio,server-tokio --test client_server -- --test-threads=1 (11/11)
- cargo test --features client,server,bare_metal --test bare_metal_e2e (2/2)
- cargo test -p simple-someip-embassy-net --test loopback (3/3)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 introduces a handle abstraction for server-side SD session state (SdStateHandle / WrappableSdStateHandle) and threads it through Server as a new type parameter (Hsd, defaulting to Arc<SdStateManager>), enabling future no-alloc usage patterns without requiring Arc<SdStateManager>.

Changes:

  • Add SdStateHandle and WrappableSdStateHandle traits plus implementations for Arc<SdStateManager> and &'static SdStateManager.
  • Make SdStateManager public and SdStateManager::new() a pub const fn to support static-storage construction.
  • Update Server to store SD state behind Hsd and use SdStateHandle::sd_state() at call sites; add method-level Send + Sync bounds for announcement_loop.

Reviewed changes

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

File Description
src/server/sd_state.rs Makes SdStateManager public/const-constructible and adds SD-state handle traits + impls.
src/server/mod.rs Adds Hsd type parameter to Server and migrates SD-state usage to the new handle abstraction.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/server/sd_state.rs
Comment on lines 29 to +33
/// once, then [`RebootFlag::Continuous`] permanently — `SdStateManager`
/// tracks that transition and exposes it via [`Self::reboot_flag`] so every
/// server-side SD emission path reads from a single source of truth.
#[derive(Debug)]
pub(super) struct SdStateManager {
pub struct SdStateManager {
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

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

SdStateManager is now public, but its rustdoc still claims it "exposes" the reboot state via Self::reboot_flag (and links to it). reboot_flag is #[cfg(test)] pub(super), so it won’t exist in normal builds and the public docs are now inaccurate / can produce a broken intra-doc link. Suggest updating this doc to describe the public surface (e.g., refer to next_session_id_with_reboot_flag semantics or state that reboot-flag tracking is internal to Server) and remove the Self::reboot_flag link rather than making that method public.

Copilot uses AI. Check for mistakes.
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.

2 participants