Skip to content

Commit

Permalink
docs: improve docstrings in the scion and scion-grpc crates
Browse files Browse the repository at this point in the history
  • Loading branch information
mlegner authored and jpcsmith committed Jan 26, 2024
1 parent 6ba79f9 commit 6b1ebe3
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 32 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
max_line_length = 120
max_line_length = 110
trim_trailing_whitespace = true

[*.md]
Expand Down
9 changes: 9 additions & 0 deletions crates/scion-grpc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
//! Bindings for [gRPC](https://grpc.io/) types and services used within SCION's control plane.
//!
//! The code is autogenerated using [tonic] from the protobuf definitions copied from the [SCION reference
//! implementation][scionproto].
//!
//! [scionproto]: https://github.com/scionproto/scion

pub use prost::Message;

pub mod drkey {
//! Types and services for dynamically re-creatable keys (DRKeys).

pub mod v1 {
//! Version 1 DRKey types.

tonic::include_proto!("proto.drkey.v1");
}
}
Expand Down
23 changes: 19 additions & 4 deletions crates/scion/src/daemon.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
//! Tools to communicate with the local SCION daemon.
//! Communicate with the local SCION daemon.
//!
//! This module provides a convenient [`DaemonClient`] to communicate with the local [SCION daemon][daemon].
//! It uses the automatically generated gRPC code in the [scion_grpc] crate.
//!
//! The daemon address can be configured using the environment variable specified in the constant
//! [`DAEMON_ADDRESS_ENV_VARIABLE`] if it differs from the default value stored in
//! [`DEFAULT_DAEMON_ADDRESS`].
//!
//! [daemon]: https://docs.scion.org/en/latest/manuals/daemon.html

mod messages;
pub use messages::{AsInfo, PathRequest};
pub use messages::{AsInfo, PathRequest, PathRequestFlags};

pub mod client;
pub use client::{get_daemon_address, DaemonClient, DaemonClientError};
mod client;
pub use client::{
get_daemon_address,
DaemonClient,
DaemonClientError,
DAEMON_ADDRESS_ENV_VARIABLE,
DEFAULT_DAEMON_ADDRESS,
};
11 changes: 7 additions & 4 deletions crates/scion/src/daemon/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,17 @@ pub const DEFAULT_DAEMON_ADDRESS: &str = "https://localhost:30255";
/// The environment variable to configure the address of the SCION daemon.
pub const DAEMON_ADDRESS_ENV_VARIABLE: &str = "SCION_DAEMON_ADDRESS";

#[allow(missing_docs)]
/// Error type returned when attempting to communicate with the SCION daemon.
#[derive(Debug, thiserror::Error)]
pub enum DaemonClientError {
#[error("A communication error occurred: {0}")]
/// A communication error occurred.
#[error("a communication error occurred: {0}")]
ConnectionError(#[from] tonic::transport::Error),
#[error("A gRPC error occurred: {0}")]
/// An error occurred in the gRPC protocol.
#[error("a gRPC error occurred: {0}")]
GrpcError(#[from] tonic::Status),
#[error("Response contained invalid data")]
/// The data returned by the SCION daemon contained invalid data.
#[error("response contained invalid data")]
InvalidData,
}

Expand Down
16 changes: 12 additions & 4 deletions crates/scion/src/daemon/messages.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![allow(missing_docs)]

use std::num::TryFromIntError;

use scion_grpc::daemon::v1::{self as daemon_grpc};
Expand Down Expand Up @@ -33,18 +31,23 @@ impl TryFrom<daemon_grpc::AsResponse> for AsInfo {
}
}

/// Path requests specifying source and destination ISD-ASN with some flags
/// Path requests specifying source and destination ISD-ASN with some flags.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct PathRequest {
/// The source ISD-ASN from which paths are requested.
pub source: IsdAsn,
/// The destination ISD-ASN to which paths are requested.
pub destination: IsdAsn,
/// Flags to request specific server behavior for this request.
pub flags: PathRequestFlags,
}

/// Flags for path requests
/// Flags for path requests.
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct PathRequestFlags {
/// Request fresh paths for this request instead of having the server reply from its cache.
pub refresh: bool,
/// Request hidden paths instead of standard paths.
pub hidden: bool,
}

Expand All @@ -60,6 +63,8 @@ impl From<&PathRequest> for daemon_grpc::PathsRequest {
}

impl PathRequest {
/// Creates a new `PathRequest` to the provided destination with default flags and using the
/// [`WILDCARD`][IsdAsn::WILDCARD] ISD-ASN indicating the local AS as the source.
pub fn new(dst_isd_asn: IsdAsn) -> Self {
Self {
source: IsdAsn::WILDCARD,
Expand All @@ -68,16 +73,19 @@ impl PathRequest {
}
}

/// Specifies an explicit source ISD-ASN in the request.
pub fn with_src_isd_asn(mut self, src_isd_asn: IsdAsn) -> Self {
self.source = src_isd_asn;
self
}

/// Sets the [refresh][PathRequestFlags::refresh] flag for the request.
pub fn with_refresh(mut self) -> Self {
self.flags.refresh = true;
self
}

/// Sets the [hidden][PathRequestFlags::hidden] flag for the request.
pub fn with_hidden(mut self) -> Self {
self.flags.hidden = true;
self
Expand Down
56 changes: 39 additions & 17 deletions crates/scion/src/dispatcher.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
#![allow(missing_docs)]
//! Communication with the SCION dispatcher through a UNIX socket.
//!
//! This module provides a convenient [`DispatcherStream`] to send and receive packets to/from a
//! [SCION dispatcher][dispatcher]. It builds on a [`UnixStream`] and uses the message types defined in the
//! [scion_proto::reliable] module.
//!
//! The path to the dispatcher socket can be configured using the environment variable specified in the
//! constant [`DISPATCHER_PATH_ENV_VARIABLE`] if it differs from the default value stored in
//! [`DEFAULT_DISPATCHER_PATH`].
//!
//! [dispatcher]: https://docs.scion.org/en/latest/manuals/dispatcher.html

use std::{
io::{self, IoSlice},
Expand Down Expand Up @@ -26,39 +36,41 @@ use tokio::{

/// Underlay port on which the dispatcher receives packets from the network.
pub const UNDERLAY_PORT: u16 = 30041;
/// The default file path of the dispatcher socket.
pub const DEFAULT_DISPATCHER_PATH: &str = "/run/shm/dispatcher/default.sock";
/// The environment variable to configure the path of the dispatcher socket.
pub const DISPATCHER_PATH_ENV_VARIABLE: &str = "SCION_DISPATCHER_PATH";

// Recv buffer to 1 MiB
// TODO(jsmith): Allow the user to set this
const RECV_BUFFER_LEN: usize = 1024 * 1024; // 1 MiB;

// Set the send buffer to 1024 bytes since only single common headers (max ~32 B) are written to it.
// This means that the logic for resetting the BytesMut is triggered only once every ~30 packets.
const SEND_BUFFER_LEN: usize = 1024;

/// The default file path of the dispatcher socket.
pub const DEFAULT_DISPATCHER_PATH: &str = "/run/shm/dispatcher/default.sock";

/// The environment variable to configure the path of the dispatcher socket.
pub const DISPATCHER_PATH_ENV_VARIABLE: &str = "SCION_DISPATCHER_PATH";

/// Get the dispatcher path.
///
/// Depending on the environment, this is the [`DEFAULT_DISPATCHER_PATH`] or manually configured
pub fn get_dispatcher_path() -> String {
std::env::var(DISPATCHER_PATH_ENV_VARIABLE).unwrap_or(DEFAULT_DISPATCHER_PATH.to_string())
}

#[allow(missing_docs)]
/// Error type returned when attempting to register with a SCION dispatcher.
#[derive(Debug, thiserror::Error)]
pub enum RegistrationError {
/// The provided registration address was invalid.
#[error("an invalid registration address was provided")]
InvalidAddress,
/// An error occurred during the registration protocol.
#[error(transparent)]
RegistrationExchangeFailed(#[from] ProtocolRegistrationError),
/// An invalid response was received from the dispatcher.
#[error(transparent)]
InvalidResponse(#[from] DecodeError),
/// The dispatcher refused to bind to the requested address.
#[error("the dispatcher refused to bind to the requested address")]
Refused,
/// An input/output error occurred.
#[error(transparent)]
Io(#[from] io::Error),
}
Expand All @@ -69,20 +81,24 @@ impl From<InvalidRegistrationAddressError> for RegistrationError {
}
}

#[allow(missing_docs)]
/// Error type returned when attempting to receive packets from a SCION dispatcher.
#[derive(Debug, thiserror::Error)]
pub enum ReceiveError {
/// An input/output error occurred.
#[error(transparent)]
Io(#[from] io::Error),
/// The received packet could not be decoded.
#[error(transparent)]
Decode(#[from] DecodeError),
}

#[allow(missing_docs)]
/// Error type returned when attempting to send packets to a SCION dispatcher.
#[derive(Debug, thiserror::Error)]
pub enum SendError {
/// An input/output error occurred.
#[error(transparent)]
Io(#[from] io::Error),
/// The packet payload is too large to be sent.
#[error("payload is too large to be sent size={0}, max={}", u32::MAX)]
PayloadTooLarge(usize),
}
Expand Down Expand Up @@ -123,7 +139,7 @@ impl DispatcherStream {

debug_assert!(self.send_buffer.is_empty());

// Known to hold all registration messages
// Known to hold all registration messages.
let mut buffer = [0u8; 64];
let message_length = exchange.register(address, &mut buffer.as_mut())?;

Expand All @@ -148,17 +164,23 @@ impl DispatcherStream {
Ok(exchange.handle_response(&packet.content)?)
}

/// Send a packet through the SCION dispatcher.
///
/// The `relay` specifies the underlay address (UDP/IP) to which the dispatcher sends the packet.
pub async fn send_packet_via<const N: usize>(
&mut self,
relay: Option<std::net::SocketAddr>,
packet: &impl WireEncodeVec<N>,
) -> Result<(), SendError> {
// we know that the buffer is large enough
// We know that the buffer is large enough.
let bytes = packet.encode_with_unchecked(&mut self.send_buffer);
let buffers: [IoSlice; N] = core::array::from_fn(|i| IoSlice::new(&bytes[i][..]));
self.send_via(relay, &buffers).await
}

/// Send data contained in a slice of buffers through the SCION dispatcher.
///
/// The `relay` specifies the underlay address (UDP/IP) to which the dispatcher sends the packet.
pub async fn send_via(
&mut self,
relay: Option<std::net::SocketAddr>,
Expand All @@ -173,24 +195,24 @@ impl DispatcherStream {
.map_err(|_| SendError::PayloadTooLarge(packet_len))?,
};

// we know that the buffer is large enough
// We know that the buffer is large enough.
header.encode_to_unchecked(&mut self.send_buffer);
self.inner.write_all_buf(&mut self.send_buffer).await?;
let _ = self.inner.write_vectored(buffers).await?;

Ok(())
}

/// Receive a packet from the dispatcher stream
/// Receive a packet from the dispatcher stream.
pub async fn receive_packet(&mut self) -> Result<Packet, ReceiveError> {
loop {
// Attempt to decode any data available in the receive buffer
// Attempt to decode any data available in the receive buffer.
if let Some(packet) = self.parser.parse(&mut self.recv_buffer)? {
return Ok(packet);
}

// Read data into the receive buffer.
// 0 bytes read indicates a EoF which (I think) should never happen for the dispatcher
// 0 bytes read indicates a EoF which (I think) should never happen for the dispatcher.
if let 0 = self.inner.read_buf(&mut self.recv_buffer).await? {
return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into());
}
Expand Down
17 changes: 16 additions & 1 deletion crates/scion/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
//! Tools to interact with SCION components, instantiate sockets, and send SCION packets.
//! End-host networking stack for the SCION Internet architecture.
//!
//! This crate contains all asynchronous code required to interact with SCION components, instantiate sockets,
//! and send SCION packets.
//!
//! # Organization
//!
//! - [daemon] contains a [`DaemonClient`][daemon::DaemonClient] to interact with the SCION daemon.
//! - [dispatcher] contains a [`DispatcherStream`][dispatcher::DispatcherStream] to send and receive packets
//! via the SCION dispatcher. It is normally not necessary to use this directly as the [`pan`] and [socket]
//! modules have tools with more convenient interfaces.
//! - [pan] contains services and strategies to manage paths as well as a datagram socket that includes this
//! path management.
//! - [socket] contains a simple [UDP socket][socket::UdpSocket] and a [raw socket][socket::RawSocket] that
//! can be used to send an receive SCMP informational messages (see
//! [`ScmpMessage`][scion_proto::scmp::ScmpMessage]).

pub mod daemon;
pub mod dispatcher;
Expand Down
7 changes: 6 additions & 1 deletion crates/scion/src/pan.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
//! Path aware networking socket and services.
//! Path-aware networking socket and services.
//!
//! This module has similar goals like the [Go pan library][pan].
//!
//! [pan]: https://pkg.go.dev/github.com/netsec-ethz/scion-apps/pkg/pan

mod datagram;
pub use datagram::{AsyncScionDatagram, PathAwareDatagram};

Expand Down
8 changes: 8 additions & 0 deletions crates/scion/src/pan/path_strategy.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
//! Strategies for caching and selecting paths.
//!
//! A path strategy must implement the trait [`PathStrategy`]. In practice, it will be used with a controller
//! like the [`AsyncPathStrategy`], which also implements the [`AsyncPathService`][super::AsyncPathService]
//! trait.
//!
//! For concrete types implementing [`PathStrategy`], see [`PathRefresher`][refresher::PathRefresher] and
//! [`UniformStrategy`][uniform::UniformStrategy].

use std::time::{Duration, Instant};

use scion_proto::{address::IsdAsn, path::Path};
Expand Down
13 changes: 13 additions & 0 deletions crates/scion/src/socket.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
//! Sockets to send different types of higher-layer messages via SCION.
//!
//! The module has a similar functionality as the [Go snet library][snet].
//!
//! The [`UdpSocket`] implements the [`AsyncScionDatagram`][crate::pan::AsyncScionDatagram] trait and can thus
//! be used to send and receive UDP datagrams with a simple interface to specify the communication paths. This
//! can be composed with additional path management implemented in the
//! [pan::path_strategy][super::pan::path_strategy] module.
//!
//! The [`RawSocket`] can be used to send manually created [`ScionPacket`s][scion_proto::packet::ScionPacket]
//! including [SCMP packets][scion_proto::packet::ScionPacketScmp] and receive [raw SCION
//! packets][scion_proto::packet::ScionPacketRaw].
//!
//! [snet]: https://pkg.go.dev/github.com/scionproto/scion/pkg/snet

mod error;
pub use error::BindError;
Expand Down

0 comments on commit 6b1ebe3

Please sign in to comment.