Skip to content

Add concrete no-spawn outstation task types under unstable #435

Description

@jadamcrain

Compatibility constraint

add_outstation_no_spawn and bind_no_spawn were released in DNP3 1.6.0. This work must not change or remove those APIs.

All new types and entry points are additive and gated by the unstable feature. The existing 1.6.0 APIs retain their current signatures and behavior.

Problem

The existing TCP outstation no-spawn APIs return opaque futures:

pub fn add_outstation_no_spawn(...)
    -> Result<(OutstationHandle, impl Future<Output = ()>), FilterError>

pub async fn bind_no_spawn(self)
    -> Result<(ServerHandle, impl Future<Output = Shutdown>), std::io::Error>

These futures cannot be named in a struct field without boxing or type erasure. This is inconvenient for staged lifecycles that configure resources, store prepared tasks, and spawn them later.

A TCP outstation server also consists of independently scheduled tasks: one accept/routing task and one adapter task per outstation. Combining them into one aggregate future would prevent Tokio from scheduling different outstations concurrently across worker threads.

Design

Add two concrete task types behind unstable.

OutstationTask

OutstationTask represents one independently runnable DNP3 outstation. Its private variants support:

  • an opened serial outstation;
  • one TCP/TLS server outstation adapter.

The serial construction path returns the common task:

pub fn SerialOutstation::open(...)
    -> std::io::Result<OutstationTask>

TCP server registration gains an additive method:

pub fn Server::add_outstation_task(...)
    -> Result<(OutstationHandle, OutstationTask), FilterError>

TcpServerTask

TcpServerTask represents only the TCP accept and connection-routing loop:

pub fn Server::into_task(
    self,
    listener: tokio::net::TcpListener,
) -> (ServerHandle, TcpServerTask)

Each task exposes a consuming asynchronous run() method. The caller runs the TCP server task and every outstation task independently, preserving the existing N+1 scheduling model and cross-core parallelism.

The concrete task APIs attach no automatic task-root tracing spans, allowing callers to apply their own instrumentation.

Status

Implemented in PR #433 by commit 55c1b4f.

  • Add common concrete OutstationTask
  • Return OutstationTask from serial open
  • Add Server::add_outstation_task
  • Return concrete TcpServerTask from Server::into_task
  • Preserve stable 1.6.0 APIs
  • Preserve independent task scheduling
  • Verify returned task futures are independently spawnable

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions