#![deny(missing_docs)]
mod client;
mod error;
mod event_loop;
pub mod meeting;
mod protocols;
mod transport;
pub(crate) use client::{client_impl, client_transport_impl};
pub use event_loop::EventStream;
pub use protocols::*;
pub use transport::{NetworkTransport, Transport};
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
mod native;
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
pub use native::{
NativeClient as Client, NativeEventLoop as EventLoop,
};
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
mod web;
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
pub use web::{WebClient as Client, WebEventLoop as EventLoop};
use mpc_protocol::{
hex, snow::params::NoiseParams, Chunk, Encoding, Keypair,
OpaqueMessage, ProtocolState, RequestMessage, SealedEnvelope,
SessionId, PATTERN,
};
use std::{collections::HashMap, sync::Arc};
use tokio::sync::RwLock;
pub(crate) type Peers = Arc<RwLock<HashMap<Vec<u8>, ProtocolState>>>;
pub(crate) type Server = Arc<RwLock<Option<ProtocolState>>>;
pub struct ClientOptions {
pub keypair: Keypair,
pub server_public_key: Vec<u8>,
pub pattern: Option<String>,
}
impl ClientOptions {
pub fn url(&self, server: &str) -> String {
let server = server.trim_end_matches('/');
format!(
"{}/?public_key={}",
server,
hex::encode(self.keypair.public_key())
)
}
pub fn params(&self) -> Result<NoiseParams> {
let pattern = self
.pattern
.as_ref()
.map(|s| &s[..])
.unwrap_or_else(|| PATTERN);
Ok(pattern.parse()?)
}
}
pub use error::Error;
pub type Result<T> = std::result::Result<T, Error>;
async fn encrypt_peer_channel(
public_key: impl AsRef<[u8]>,
peer: &mut ProtocolState,
payload: &[u8],
encoding: Encoding,
broadcast: bool,
session_id: Option<SessionId>,
) -> Result<RequestMessage> {
match peer {
ProtocolState::Transport(transport) => {
let chunks = Chunk::split(payload, transport)?;
let envelope = SealedEnvelope {
encoding,
chunks,
broadcast,
};
let request =
RequestMessage::Opaque(OpaqueMessage::PeerMessage {
public_key: public_key.as_ref().to_vec(),
session_id,
envelope,
});
Ok(request)
}
_ => Err(Error::NotTransportState),
}
}
async fn decrypt_peer_channel(
peer: &mut ProtocolState,
envelope: SealedEnvelope,
) -> Result<(Encoding, Vec<u8>)> {
match peer {
ProtocolState::Transport(transport) => {
let contents = Chunk::join(envelope.chunks, transport)?;
Ok((envelope.encoding, contents))
}
_ => Err(Error::NotTransportState),
}
}