docs(server): add executable API examples
This commit is contained in:
4 files changed
+93
No files matched your search
@@ -98,6 +98,28 @@ pub enum TimestampAllowance {
|
|||||||
/// [`max_packet_length`](Self::max_packet_length) like every other reply, and
|
/// [`max_packet_length`](Self::max_packet_length) like every other reply, and
|
||||||
/// `none` is zero-filled here rather than left as residue. An operator
|
/// `none` is zero-filled here rather than left as residue. An operator
|
||||||
/// restriction can be added if a real use case turns up.
|
/// restriction can be added if a real use case turns up.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// Configure a modest per-listener session budget and restrict timestamp
|
||||||
|
/// placement while leaving DSCP marking disabled:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::time::Duration;
|
||||||
|
///
|
||||||
|
/// use irtt_server::{ServerConfig, TimestampAllowance};
|
||||||
|
///
|
||||||
|
/// let config = ServerConfig::default()
|
||||||
|
/// .with_max_sessions(128)
|
||||||
|
/// .with_idle_timeout(Duration::from_secs(30))
|
||||||
|
/// .with_timestamp_allowance(TimestampAllowance::Single)
|
||||||
|
/// .with_dscp_allowed(false);
|
||||||
|
///
|
||||||
|
/// assert_eq!(config.max_sessions(), 128);
|
||||||
|
/// assert_eq!(config.idle_timeout(), Duration::from_secs(30));
|
||||||
|
/// assert_eq!(config.timestamp_allowance(), TimestampAllowance::Single);
|
||||||
|
/// assert!(!config.dscp_allowed());
|
||||||
|
/// ```
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct ServerConfig {
|
pub struct ServerConfig {
|
||||||
hmac_key: Option<Vec<u8>>,
|
hmac_key: Option<Vec<u8>>,
|
||||||
|
|||||||
@@ -47,6 +47,32 @@ use crate::{
|
|||||||
/// a transport abstraction, and there is no blocking or alternate-runtime
|
/// a transport abstraction, and there is no blocking or alternate-runtime
|
||||||
/// counterpart.
|
/// counterpart.
|
||||||
///
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// The core can be driven directly with a normally encoded open request. It
|
||||||
|
/// returns a reply to send and records the new session without performing I/O:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::net::{Ipv4Addr, SocketAddr};
|
||||||
|
///
|
||||||
|
/// use irtt_proto::{decode_open_reply, encode_request, Params, RequestToEncode};
|
||||||
|
/// use irtt_server::{ServerConfig, ServerCore};
|
||||||
|
///
|
||||||
|
/// let peer = SocketAddr::from((Ipv4Addr::LOCALHOST, 40_000));
|
||||||
|
/// let mut core = ServerCore::new(ServerConfig::default());
|
||||||
|
/// let params = Params::with_protocol_defaults();
|
||||||
|
/// let request = encode_request(
|
||||||
|
/// RequestToEncode::Open { params: ¶ms, no_test: false },
|
||||||
|
/// None,
|
||||||
|
/// )
|
||||||
|
/// .unwrap();
|
||||||
|
///
|
||||||
|
/// let reply = core.handle_datagram(peer, &request).unwrap().unwrap();
|
||||||
|
/// let open = decode_open_reply(reply.bytes(), None).unwrap();
|
||||||
|
/// assert_ne!(open.token, 0);
|
||||||
|
/// assert_eq!(core.session_count(), 1);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
/// # Scope
|
/// # Scope
|
||||||
///
|
///
|
||||||
/// The core implements open handling, session creation and negotiation,
|
/// The core implements open handling, session creation and negotiation,
|
||||||
|
|||||||
@@ -53,6 +53,28 @@ const MAINTENANCE_INTERVAL: Duration = Duration::from_secs(1);
|
|||||||
/// [`ServerRuntimeError::WildcardSourceSelectionUnsupported`] — rather than
|
/// [`ServerRuntimeError::WildcardSourceSelectionUnsupported`] — rather than
|
||||||
/// served by a listener whose replies a client on a second address would
|
/// served by a listener whose replies a client on a second address would
|
||||||
/// silently discard. Explicit-address listeners are unaffected everywhere.
|
/// silently discard. Explicit-address listeners are unaffected everywhere.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// Bind one listener, inspect the resolved endpoint, and let the caller decide
|
||||||
|
/// when serving ends. This example type-checks without opening a socket:
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// use std::{net::{Ipv4Addr, SocketAddr}, time::Duration};
|
||||||
|
///
|
||||||
|
/// use irtt_server::{Server, ServerConfig};
|
||||||
|
///
|
||||||
|
/// # async fn serve() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
/// let mut server = Server::bind(
|
||||||
|
/// SocketAddr::from((Ipv4Addr::LOCALHOST, 0)),
|
||||||
|
/// ServerConfig::default(),
|
||||||
|
/// )
|
||||||
|
/// .await?;
|
||||||
|
/// println!("listening on {}", server.local_addr()?);
|
||||||
|
/// server.run(tokio::time::sleep(Duration::from_secs(60))).await?;
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
socket: UdpSocket,
|
socket: UdpSocket,
|
||||||
|
|||||||
@@ -57,6 +57,29 @@ use crate::{Server, ServerConfig, ServerRuntimeError};
|
|||||||
/// whole set: a service configured for IPv4 and IPv6 must not quietly continue
|
/// whole set: a service configured for IPv4 and IPv6 must not quietly continue
|
||||||
/// as IPv4 only. Every listener task is joined before `run` returns, so no task
|
/// as IPv4 only. Every listener task is joined before `run` returns, so no task
|
||||||
/// outlives it.
|
/// outlives it.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// Bind independent listeners, inspect their resolved addresses, then serve
|
||||||
|
/// them under one caller-owned shutdown future. This example type-checks
|
||||||
|
/// without binding sockets:
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// use std::{net::{Ipv4Addr, SocketAddr}, time::Duration};
|
||||||
|
///
|
||||||
|
/// use irtt_server::{ServerConfig, ServerSet};
|
||||||
|
///
|
||||||
|
/// # async fn serve() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
/// let addrs = [
|
||||||
|
/// SocketAddr::from((Ipv4Addr::LOCALHOST, 0)),
|
||||||
|
/// SocketAddr::from((Ipv4Addr::LOCALHOST, 0)),
|
||||||
|
/// ];
|
||||||
|
/// let set = ServerSet::bind(addrs, ServerConfig::default()).await?;
|
||||||
|
/// println!("listening on {:?}", set.local_addrs());
|
||||||
|
/// set.run(tokio::time::sleep(Duration::from_secs(60))).await?;
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ServerSet {
|
pub struct ServerSet {
|
||||||
servers: Vec<Server>,
|
servers: Vec<Server>,
|
||||||
|
|||||||
Reference in new issue
Block a user