zerodds_websocket_bridge/lib.rs
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 ZeroDDS Contributors
3
4//! Crate `zerodds-websocket-bridge`. Safety classification: **STANDARD**.
5//!
6//! WebSocket (RFC 6455) komplettes Stack-Set — pure-Rust `no_std +
7//! alloc`, `forbid(unsafe_code)`. Implementiert die volle WebSocket-
8//! Spec inklusive Base-Framing-Protocol (§5.2 + §5.3), Opening-
9//! Handshake (§4) mit `Sec-WebSocket-Accept`-SHA1-Berechnung,
10//! Extension- + Subprotocol-Negotiation (§9), Close-Frame-Status-
11//! Code-Semantik (§7.4) inkl. Forbidden-on-Wire-Pruefung,
12//! permessage-deflate Extension (RFC 7692), URI-Parser (`ws://` /
13//! `wss://`, RFC 6455 §3), Streaming-UTF-8-Validator (§8.1) fuer
14//! Text-Frames, sowie einen WebSocket↔DDS-Topic-Bridge.
15//!
16//! Spec-Referenzen:
17//!
18//! - **RFC 6455** — The WebSocket Protocol.
19//! - **RFC 7692** — Compression Extensions for WebSocket
20//! (`permessage-deflate`).
21//!
22//! ## Schichten-Position
23//!
24//! Layer 5 — Bridges. Substrat fuer Browser↔DDS-Endpoint-Mapping
25//! (Web-UIs, Realtime-Dashboards, DDS-Web-Gateway).
26//!
27//! ## Public API (Stand 1.0.0-rc.1)
28//!
29//! - [`Frame`] / [`Opcode`] — Frame-Modell (§5.2).
30//! - [`encode`] / [`decode`] / [`CodecError`] — Wire-Codec inklusive
31//! Payload-Length-Encoding (7-bit / 7+16-bit / 7+64-bit) und
32//! Masking-Application.
33//! - [`apply_mask`] / [`generate_masking_key`] /
34//! [`MaskingKeyProvider`] / [`InsecureSplitmixProvider`] /
35//! [`ClosureMaskingKeyProvider`] — XOR-Masking (§5.3).
36//! - [`CloseCode`] / [`ClosePayload`] / [`encode_close_payload`] /
37//! [`decode_close_payload`] — Close-Frame-Codec (§7.4).
38//! - [`ClientHandshake`] / [`ServerHandshake`] /
39//! [`compute_accept`] / [`parse_client_request`] /
40//! [`build_server_response`] / [`render_server_response`] /
41//! [`HandshakeError`] — Opening-Handshake (§4).
42//! - [`PermessageDeflateParams`] / [`parse_offer`] / [`render_accept`]
43//! / [`append_tail`] / [`strip_tail`] / [`DEFLATE_TAIL`] /
44//! [`NegotiationError`] — RFC 7692 permessage-deflate Negotiation.
45//! - [`WebSocketUri`] / [`parse_websocket_uri`] / [`default_port`] /
46//! [`is_local_loopback`] / [`resource_name`] / [`UriError`] —
47//! `ws://` / `wss://` URI-Parser (§3).
48//! - [`StreamingValidator`] / [`validate_utf8`] / [`Utf8Error`] —
49//! Text-Frame-UTF-8-Validator (§8.1).
50//! - [`SubscriptionRegistry`] / [`Notification`] / [`BridgeOp`] /
51//! [`BridgeError`] / [`parse_op`] / [`render_notification`] —
52//! WebSocket↔DDS-Topic-Bridge.
53//!
54//! ## Beispiel
55//!
56//! ```rust
57//! use zerodds_websocket_bridge::{compute_accept};
58//!
59//! // RFC 6455 §1.3: Sec-WebSocket-Accept-Beispiel.
60//! let accept = compute_accept("dGhlIHNhbXBsZSBub25jZQ==");
61//! assert_eq!(accept, "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=");
62//! ```
63
64#![forbid(unsafe_code)]
65#![warn(missing_docs)]
66#![allow(
67 clippy::expect_used,
68 clippy::unwrap_used,
69 clippy::panic,
70 clippy::print_stderr,
71 clippy::print_stdout,
72 clippy::field_reassign_with_default,
73 clippy::manual_flatten,
74 clippy::collapsible_if,
75 clippy::empty_line_after_doc_comments,
76 clippy::approx_constant,
77 clippy::unreachable,
78 clippy::uninlined_format_args,
79 clippy::drop_non_drop,
80 clippy::useless_conversion,
81 clippy::manual_strip,
82 missing_docs
83)]
84
85extern crate alloc;
86
87pub mod close;
88pub mod codec;
89#[cfg(feature = "daemon")]
90pub mod daemon;
91pub mod dds_bridge;
92pub mod frame;
93pub mod handshake;
94pub mod masking;
95pub mod message;
96pub mod negotiation;
97pub mod permessage_deflate;
98pub mod uri;
99pub mod utf8;
100
101pub use close::{CloseCode, ClosePayload, decode_close_payload, encode_close_payload};
102pub use codec::{CodecError, decode, encode};
103pub use dds_bridge::{
104 BridgeError, BridgeOp, Notification, SubscriptionRegistry, parse_op, render_notification,
105};
106pub use frame::{Frame, Opcode};
107pub use handshake::{
108 ClientHandshake, HandshakeError, ServerHandshake, build_server_response, compute_accept,
109 parse_client_request, render_server_response,
110};
111pub use masking::{
112 ClosureMaskingKeyProvider, InsecureSplitmixProvider, MaskingKeyProvider, apply_mask,
113 generate_masking_key,
114};
115pub use permessage_deflate::{
116 DEFLATE_TAIL, NegotiationError, PermessageDeflateParams, append_tail, parse_offer,
117 render_accept, strip_tail,
118};
119pub use uri::{
120 UriError, WebSocketUri, default_port, is_local_loopback, parse_websocket_uri, resource_name,
121};
122pub use utf8::{StreamingValidator, Utf8Error, validate as validate_utf8};