pub mod call;
pub(crate) mod client;
pub(crate) mod dyn_wrapper;
mod local;
#[cfg(feature = "tls-rustls")]
pub mod rustls;
pub(crate) mod server;
use std::sync::Arc;
pub use client::CompositeChannelCredentials;
pub use local::LocalChannelCredentials;
pub use local::LocalServerCredentials;
use crate::credentials::call::CallCredentials;
use crate::credentials::client::ClientConnectionSecurityContext;
use crate::credentials::client::ClientHandshakeInfo;
use crate::credentials::client::HandshakeOutput;
use crate::credentials::common::Authority;
use crate::private;
use crate::rt::GrpcEndpoint;
use crate::rt::GrpcRuntime;
#[trait_variant::make(Send)]
pub trait ChannelCredentials: Sync + 'static {
#[doc(hidden)]
type ContextType: ClientConnectionSecurityContext;
#[doc(hidden)]
type Output<I>;
fn info(&self) -> &ProtocolInfo;
#[doc(hidden)]
fn get_call_credentials(&self, token: private::Internal) -> Option<&Arc<dyn CallCredentials>>;
#[doc(hidden)]
async fn connect<Input: GrpcEndpoint>(
&self,
authority: &Authority,
source: Input,
info: &ClientHandshakeInfo,
runtime: &GrpcRuntime,
token: private::Internal,
) -> Result<HandshakeOutput<Self::Output<Input>, Self::ContextType>, String>;
}
#[trait_variant::make(Send)]
pub trait ServerCredentials: Sync + 'static {
#[doc(hidden)]
type Output<I>;
fn info(&self) -> &ProtocolInfo;
#[doc(hidden)]
async fn accept<Input: GrpcEndpoint>(
&self,
source: Input,
runtime: GrpcRuntime,
token: private::Internal,
) -> Result<server::HandshakeOutput<Self::Output<Input>>, String>;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[non_exhaustive]
pub enum SecurityLevel {
NoSecurity,
IntegrityOnly,
PrivacyAndIntegrity,
}
pub(crate) mod common {
#[derive(Clone, PartialEq, Debug)]
pub struct Authority {
host: String,
port: Option<u16>,
}
impl Authority {
pub fn new(host: impl Into<String>, port: Option<u16>) -> Self {
Self {
host: host.into(),
port,
}
}
pub fn host(&self) -> &str {
&self.host
}
pub fn port(&self) -> Option<u16> {
self.port
}
pub fn host_port_string(&self) -> String {
let host_str = &self.host;
match self.port() {
None => host_str.to_string(),
Some(port) if host_str.contains(':') => {
format!("[{}]:{}", host_str, port)
}
Some(port) => format!("{}:{}", host_str, port),
}
}
}
}
pub struct ProtocolInfo {
security_protocol: &'static str,
}
impl ProtocolInfo {
pub(crate) const fn new(security_protocol: &'static str) -> Self {
Self { security_protocol }
}
pub fn security_protocol(&self) -> &'static str {
self.security_protocol
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn authority_host_port_str() {
let authority = Authority::new("localhost", None);
assert_eq!(&authority.host_port_string(), "localhost");
let authority = Authority::new("localhost", Some(443));
assert_eq!(&authority.host_port_string(), "localhost:443");
let authority = Authority::new("::1", Some(50051));
assert_eq!(&authority.host_port_string(), "[::1]:50051");
let authority = Authority::new("::1", None);
assert_eq!(&authority.host_port_string(), "::1");
}
}