blob: c2f1726fd0f90ba2af5a90fda524eed280691d0a [file] [view]
# openprot-mctp-api
Platform-independent MCTP types, traits, and stack facade.
## Overview
This crate defines the API contract between MCTP applications and the MCTP server.
It provides two layers:
1. **`MctpClient` trait** low-level service-transport interface for
`req`, `listener`, `recv`, `send`, `drop_handle`, plus local EID control
(`get_eid` / `set_eid`). Platform-specific clients implement this trait
over a chosen transport (for example Pigweed IPC, sockets, or test doubles).
2. **`Stack` facade** (`stack` module) high-level entry point that wraps any `MctpClient`
and returns typed channel objects (`StackListener`, `StackReqChannel`, `StackRespChannel`)
that implement the `MctpListener` / `MctpReqChannel` / `MctpRespChannel` traits.
This two-layer design hides both the **concrete MCTP stack implementation** (which lives
inside the server process) and the **transport mechanism** from application code.
Applications depend only on the high-level traits; swapping the transport or stack
requires no application changes.
```text
┌─────────────────────┐
│ Application │ uses Stack facade, then channel traits
└─────────┬───────────┘
┌─────────────────────┐
│ Stack (this crate)│ wraps any MctpClient, returns typed channel handles
└─────────┬───────────┘
│ MctpClient trait
┌─────────────────────┐
│ MctpClient impl │ encodes wire protocol, uses a transport backend
│ (IPC/sockets/test) │
└─────────┬───────────┘
│ Transport
┌─────────────────────┐
│ MCTP Server │ owns the concrete MCTP stack (mctp-lib, etc.)
└─────────────────────┘
```
## Key Types
- `Handle` opaque handle for listeners, request, or response channels
- `RecvMetadata` metadata from a successful receive (msg_type, tag, remote_eid, payload_size)
- `MctpError` / `ResponseCode` error types (InternalError, NoSpace, AddrInUse, TimedOut, BadArgument, ServerRestarted)
## High-level API (`stack` module)
| Type | Trait | Obtained via |
|------|-------|--------------|
| `Stack<C>` | | `Stack::new(client)` |
| `StackListener<'_, C>` | `MctpListener` | `stack.listener(msg_type, timeout)` |
| `StackReqChannel<'_, C>` | `MctpReqChannel` | `stack.req(eid, timeout)` |
| `StackRespChannel<'_, C>` | `MctpRespChannel` | returned by `StackListener::recv` |
All channel types release their server-side handle automatically on `Drop`.
## Low-level API (`MctpClient` trait)
| Method | Description |
|--------|-------------|
| `req(eid)` | Allocate a request handle for a remote EID |
| `listener(msg_type)` | Register to receive messages of a given type |
| `get_eid() / set_eid(eid)` | Read/write the local endpoint ID |
| `recv(handle, timeout, buf)` | Receive a message on a handle |
| `send(handle, msg_type, eid, tag, ic, buf)` | Send a message (request or response) |
| `drop_handle(handle)` | Release a handle |
## Design: Strategy Pattern
`Stack<C: MctpClient>` applies the **Strategy pattern**:
- **Context** `Stack<C>` holds the strategy and exposes the high-level API
- **Strategy trait** `MctpClient` defines the service-transport operations (`req`, `listener`, `recv`, `send`, `drop_handle`) and local EID control (`get_eid`/`set_eid`).
- **Concrete strategies** transport-specific `MctpClient` implementations (for example IPC clients) and test `DirectClient`
Application code enters through the `Stack` facade and then operates on channels
implementing `MctpListener` / `MctpReqChannel` / `MctpRespChannel`. During
initialization, a concrete `MctpClient` is provided to `Stack::new(client)`;
after that, protocol logic remains transport-agnostic.
This gives two independent axes of variation:
| Concern | How to swap |
|---------|-------------|
| MCTP stack implementation (mctp-lib, etc.) | Replace the server process no API change |
| OS / IPC transport | Provide a different `MctpClient` impl to `Stack::new` |
| Application logic | Written against the high-level traits unchanged across both |
The `wire` module implements binary request/response encoding.
It is used internally by transport client implementations and server endpoints;
applications do not use it directly.
## Dependencies
This crate currently has no external Rust crate dependencies.
It is no_std compatible and relies on core plus internal modules.