use core::fmt;
use std::collections::HashSet;
use std::{
any::{Any, TypeId},
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
};
use serde::{Deserialize, Serialize};
use web_time::SystemTime;
use ng_repo::errors::*;
use ng_repo::log::*;
use ng_repo::store::Store;
use ng_repo::types::*;
use ng_repo::utils::{sign, verify};
use crate::app_protocol::*;
use crate::utils::{
get_domain_without_port_443, is_ipv4_private, is_ipv6_private, is_private_ip, is_public_ip,
is_public_ipv4, is_public_ipv6,
};
use crate::WS_PORT_ALTERNATE;
use crate::{actor::EActor, actors::admin::*, actors::*};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Credentials {
pub user_key: PrivKey,
pub read_cap: ReadCap,
pub private_store: RepoId,
pub protected_store: RepoId,
pub public_store: RepoId,
pub user_master_key: SymKey,
pub peer_priv_key: PrivKey,
}
impl Credentials {
pub fn new_partial(user_priv_key: &PrivKey) -> Self {
Credentials {
user_key: user_priv_key.clone(),
read_cap: ReadCap::nil(),
private_store: RepoId::nil(),
protected_store: RepoId::nil(),
public_store: RepoId::nil(),
user_master_key: SymKey::random(),
peer_priv_key: PrivKey::random_ed(),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum InterfaceType {
Loopback,
Private,
Public,
Invalid,
}
impl InterfaceType {
pub fn is_ip_valid_for_type(&self, ip: &IP) -> bool {
self.is_ipaddr_valid_for_type(&ip.into())
}
pub fn is_ipaddr_valid_for_type(&self, ip: &IpAddr) -> bool {
match ip {
IpAddr::V4(v4) => self.is_ipv4_valid_for_type(v4),
IpAddr::V6(v6) => self.is_ipv6_valid_for_type(v6),
}
}
pub fn is_ipv4_valid_for_type(&self, ip: &Ipv4Addr) -> bool {
match self {
InterfaceType::Loopback => ip.is_loopback(),
InterfaceType::Public => is_public_ipv4(ip),
InterfaceType::Private => is_ipv4_private(ip),
_ => false,
}
}
pub fn is_ipv6_valid_for_type(&self, ip: &Ipv6Addr) -> bool {
match self {
InterfaceType::Loopback => ip.is_loopback(),
InterfaceType::Public => is_public_ipv6(ip),
InterfaceType::Private => is_ipv6_private(ip),
_ => false,
}
}
}
#[cfg(not(target_arch = "wasm32"))]
#[derive(Clone, Debug)]
pub struct Interface {
pub if_type: InterfaceType,
pub name: String,
pub mac_addr: Option<netdev::mac::MacAddr>,
pub ipv4: Vec<netdev::ip::Ipv4Net>,
pub ipv6: Vec<netdev::ip::Ipv6Net>,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct BindAddress {
pub port: u16,
pub ip: IP,
}
impl BindAddress {
pub fn to_ws_url(&self) -> String {
format!(
"ws://{}:{}",
self.ip,
if self.port == 0 { 80 } else { self.port }
)
}
pub fn new_localhost_with_port(port: u16) -> Self {
BindAddress {
ip: LOOPBACK_IPV4.clone(),
port,
}
}
}
impl From<&SocketAddr> for BindAddress {
#[inline]
fn from(addr: &SocketAddr) -> BindAddress {
let ip_addr = addr.ip();
let ip = IP::try_from(&ip_addr).unwrap();
let port = addr.port();
BindAddress { ip, port }
}
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct BrokerCoreV0 {
pub peer_id: PubKey,
pub addrs: Vec<BindAddress>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Hash)]
pub enum BrokerCore {
V0(BrokerCoreV0),
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum BrokerServerTypeV0 {
Localhost(u16), BoxPrivate(Vec<BindAddress>),
Public(Vec<BindAddress>),
BoxPublicDyn(Vec<BindAddress>), Domain(String), }
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct BrokerServerV0 {
pub server_type: BrokerServerTypeV0,
pub can_verify: bool,
pub can_forward: bool,
pub peer_id: PubKey,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct BrokerServerContentV0 {
pub servers: Vec<BrokerServerTypeV0>,
pub version: u32,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct BrokerServer {
pub content: BrokerServerContentV0,
pub peer_id: PubKey,
pub sig: Option<Sig>,
}
pub type LocatorV0 = Vec<BrokerServer>;
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum Locator {
V0(LocatorV0),
}
impl fmt::Display for Locator {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let ser = serde_bare::to_vec(&self).unwrap();
write!(f, "{}", base64_url::encode(&ser))
}
}
impl Locator {
pub fn empty() -> Self {
Self::V0(vec![])
}
pub fn first_broker_server(&self) -> Result<BrokerServerV0, NgError> {
match self {
Self::V0(v0) => {
let bs = v0.get(0).ok_or(NgError::BrokerNotFound)?;
Ok(BrokerServerV0 {
server_type: bs
.content
.servers
.get(0)
.ok_or(NgError::BrokerNotFound)?
.clone(),
can_verify: false,
can_forward: false,
peer_id: bs.peer_id,
})
}
}
}
pub fn add(&mut self, bs: BrokerServerV0) {
match self {
Self::V0(v0) => {
for b in v0.iter_mut() {
if b.peer_id == bs.peer_id {
b.content.servers.push(bs.server_type);
return;
}
}
v0.push(BrokerServer {
peer_id: bs.peer_id,
sig: None,
content: BrokerServerContentV0 {
version: 0,
servers: vec![bs.server_type],
},
});
}
}
}
}
impl TryFrom<&str> for Locator {
type Error = NgError;
fn try_from(string: &str) -> Result<Self, NgError> {
let vec = base64_url::decode(string).map_err(|_| NgError::InvalidKey)?;
Ok(serde_bare::from_slice(&vec).map_err(|_| NgError::InvalidKey)?)
}
}
impl From<BrokerServerV0> for Locator {
fn from(bs: BrokerServerV0) -> Self {
Locator::V0(vec![BrokerServer {
peer_id: bs.peer_id,
content: BrokerServerContentV0 {
version: 0,
servers: vec![bs.server_type],
},
sig: None,
}])
}
}
#[doc(hidden)]
pub const APP_ACCOUNT_REGISTERED_SUFFIX: &str = "/#/user/registered";
#[doc(hidden)]
pub const NG_NET_URL: &str = "https://nextgraph.net";
#[doc(hidden)]
pub const NG_APP_URL: &str = "https://nextgraph.app";
#[doc(hidden)]
pub const APP_NG_WS_URL: &str = "wss://nextgraph.app";
#[allow(dead_code)]
fn api_dyn_peer_url(peer_id: &PubKey) -> String {
format!("https://nextgraph.net/api/v1/dynpeer/{}", peer_id)
}
#[doc(hidden)]
pub const LOCAL_HOSTS: [&str; 3] = ["localhost", "127.0.0.1", "[::1]"];
fn local_ws_url(port: &u16) -> String {
format!("ws://localhost:{}", if *port == 0 { 80 } else { *port })
}
#[doc(hidden)]
pub(crate) fn local_http_url(port: &u16) -> String {
format!("http://localhost:{}", if *port == 0 { 80 } else { *port })
}
#[doc(hidden)]
pub const LOCAL_URLS: [&str; 3] = ["http://localhost", "http://127.0.0.1", "http://[::1]"];
use url::{Host, Url};
impl BrokerServerTypeV0 {
pub fn find_first_ipv4(&self) -> Option<&BindAddress> {
match self {
Self::BoxPrivate(addrs) => {
for addr in addrs {
if addr.ip.is_v4() {
return Some(addr);
}
}
return None;
}
_ => None,
}
}
pub fn find_first_ipv6(&self) -> Option<&BindAddress> {
match self {
Self::BoxPrivate(addrs) => {
for addr in addrs {
if addr.ip.is_v6() {
return Some(addr);
}
}
return None;
}
_ => None,
}
}
}
impl BrokerServerV0 {
pub fn new_localhost(peer_id: PubKey) -> Self {
BrokerServerV0 {
server_type: BrokerServerTypeV0::Localhost(WS_PORT_ALTERNATE[0]),
can_verify: false,
can_forward: true,
peer_id,
}
}
fn first_ipv4(&self) -> Option<(String, Vec<BindAddress>)> {
self.server_type.find_first_ipv4().map_or(None, |bindaddr| {
Some((format!("ws://{}:{}", bindaddr.ip, bindaddr.port), vec![]))
})
}
fn first_ipv6(&self) -> Option<(String, Vec<BindAddress>)> {
self.server_type.find_first_ipv6().map_or(None, |bindaddr| {
Some((format!("ws://{}:{}", bindaddr.ip, bindaddr.port), vec![]))
})
}
pub fn first_ipv4_http(&self) -> Option<String> {
self.server_type.find_first_ipv4().map_or(None, |bindaddr| {
Some(format!("http://{}:{}", bindaddr.ip, bindaddr.port))
})
}
pub fn first_ipv6_http(&self) -> Option<String> {
self.server_type.find_first_ipv6().map_or(None, |bindaddr| {
Some(format!("http://{}:{}", bindaddr.ip, bindaddr.port))
})
}
fn first_ipv6_or_ipv4(
ipv4: bool,
ipv6: bool,
addrs: &Vec<BindAddress>,
) -> Option<&BindAddress> {
if ipv6 {
for addr in addrs {
if addr.ip.is_v6() {
return Some(addr);
}
}
}
if ipv4 {
for addr in addrs {
if addr.ip.is_v4() {
return Some(addr);
}
}
}
return None;
}
fn ng_app_bootstrap_url(addr: &BindAddress, key: PubKey) -> Option<String> {
let payload = (addr, key);
let payload_ser = serde_bare::to_vec(&payload).ok();
if payload_ser.is_none() {
return None;
}
Some(format!(
"{}?b={}",
NG_APP_URL,
base64_url::encode(&payload_ser.unwrap())
))
}
fn ng_app_bootstrap_url_with_first_ipv6_or_ipv4(
ipv4: bool,
ipv6: bool,
addrs: &Vec<BindAddress>,
key: PubKey,
) -> Option<String> {
if let Some(addr) = Self::first_ipv6_or_ipv4(ipv4, ipv6, addrs) {
return Self::ng_app_bootstrap_url(addr, key);
}
None
}
pub async fn get_url_for_ngnet(&self, ipv4: bool, ipv6: bool) -> Option<String> {
match &self.server_type {
BrokerServerTypeV0::Public(addrs) => {
Self::ng_app_bootstrap_url_with_first_ipv6_or_ipv4(
ipv4,
ipv6,
addrs,
self.peer_id,
)
}
BrokerServerTypeV0::BoxPublicDyn(addrs) => {
if addrs.len() > 0 {
Self::ng_app_bootstrap_url_with_first_ipv6_or_ipv4(
ipv4,
ipv6,
&addrs,
self.peer_id,
)
} else {
None
}
}
BrokerServerTypeV0::Domain(domain) => Some(format!("https://{}", domain)),
BrokerServerTypeV0::Localhost(port) => Some(local_http_url(&port)),
BrokerServerTypeV0::BoxPrivate(_) => {
if ipv6 {
let v6 = self.server_type.find_first_ipv6().map_or(None, |bindaddr| {
Some(format!("http://{}:{}", bindaddr.ip, bindaddr.port))
});
if v6.is_some() {
return v6;
}
}
if ipv4 {
self.server_type.find_first_ipv4().map_or(None, |bindaddr| {
Some(format!("http://{}:{}", bindaddr.ip, bindaddr.port))
})
} else {
None
}
}
}
}
pub fn is_public_server(&self) -> bool {
match &self.server_type {
BrokerServerTypeV0::Localhost(_) => false,
BrokerServerTypeV0::BoxPrivate(_) => false,
BrokerServerTypeV0::Public(_) => true,
BrokerServerTypeV0::BoxPublicDyn(_) => true,
BrokerServerTypeV0::Domain(_) => true,
}
}
pub fn get_domain(&self) -> Option<String> {
if let BrokerServerTypeV0::Domain(domain) = &self.server_type {
Some(domain.clone())
} else {
None
}
}
pub async fn get_ws_url(
&self,
location: &Option<String>,
) -> Option<(String, Vec<BindAddress>)> {
if location.is_some() {
let location = location.as_ref().unwrap();
if location.starts_with(NG_APP_URL) {
match &self.server_type {
BrokerServerTypeV0::Public(addrs) => {
Some((APP_NG_WS_URL.to_string(), addrs.clone()))
}
BrokerServerTypeV0::BoxPublicDyn(addrs) => {
if addrs.len() > 0 {
Some((APP_NG_WS_URL.to_string(), addrs.clone()))
} else {
None
}
}
_ => None,
}
} else if let BrokerServerTypeV0::Domain(domain) = &self.server_type {
let url = format!("https://{}", domain);
if location.starts_with(&url) {
let wss_url = format!("wss://{}", domain);
Some((wss_url, vec![]))
} else {
None
}
} else {
if location.starts_with(LOCAL_URLS[0])
|| location.starts_with(LOCAL_URLS[1])
|| location.starts_with(LOCAL_URLS[2])
{
if let BrokerServerTypeV0::Localhost(port) = self.server_type {
Some((local_ws_url(&port), vec![]))
} else {
None
}
}
else if location.starts_with("http://") {
let url = Url::parse(&location).unwrap();
match url.host() {
Some(Host::Ipv4(ip)) => {
if is_ipv4_private(&ip) {
self.first_ipv4()
} else {
None
}
}
Some(Host::Ipv6(ip)) => {
if is_ipv6_private(&ip) {
self.first_ipv6()
} else {
None
}
}
_ => None,
}
} else {
None
}
}
} else {
match &self.server_type {
BrokerServerTypeV0::Localhost(port) => Some((local_ws_url(port), vec![])),
BrokerServerTypeV0::BoxPrivate(addrs) => Some((String::new(), addrs.clone())),
BrokerServerTypeV0::Public(addrs) => Some((String::new(), addrs.clone())),
BrokerServerTypeV0::BoxPublicDyn(addrs) => {
if addrs.len() > 0 {
Some((String::new(), addrs.clone()))
} else {
None
}
}
BrokerServerTypeV0::Domain(domain) => Some((format!("wss://{}", domain), vec![])),
}
}
}
pub fn to_iframe_msg(&self) -> BootstrapIframeMsg {
match &self.server_type {
BrokerServerTypeV0::Domain(domain) => BootstrapIframeMsg::domain(domain.clone()),
BrokerServerTypeV0::Localhost(port) => BootstrapIframeMsg::local(*port, self.peer_id),
BrokerServerTypeV0::BoxPrivate(addrs) => BootstrapIframeMsg::private(addrs.to_vec(), self.peer_id),
BrokerServerTypeV0::Public(_) | BrokerServerTypeV0::BoxPublicDyn(_) => BootstrapIframeMsg::ngbox(),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BootstrapIframeMsg {
pub peer_id: Option<String>,
pub private: Option<Vec<BindAddress>>,
pub ngbox: Option<bool>,
pub domain: Option<String>,
pub localhost: Option<u16>,
}
impl BootstrapIframeMsg {
fn new() -> Self {
Self {
peer_id:None,
private:None,
ngbox:None,
domain:None,
localhost:None
}
}
fn domain(domain: String) -> Self {
let mut s = Self::new();
s.domain = Some(domain);
s
}
fn ngbox() -> Self {
let mut s = Self::new();
s.ngbox = Some(true);
s
}
fn private(addrs: Vec<BindAddress>, peer_id: PubKey) -> Self {
let mut s = Self::new();
s.peer_id = Some(peer_id.to_string());
s.private = Some(addrs);
s
}
fn local(port: u16, peer_id: PubKey) -> Self {
let mut s = Self::new();
s.peer_id = Some(peer_id.to_string());
s.localhost = Some(port);
s
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BootstrapContentV0 {
pub servers: Vec<BrokerServerV0>,
}
impl BootstrapContentV0 {
pub fn new_localhost(peer_id: PubKey) -> Self {
BootstrapContentV0 {
servers: vec![BrokerServerV0::new_localhost(peer_id)],
}
}
pub fn new_empty() -> Self {
BootstrapContentV0 { servers: vec![] }
}
pub fn merge(&mut self, with: &BootstrapContentV0) {
'outer: for server2 in &with.servers {
for server1 in &self.servers {
if *server1 == *server2 {
continue 'outer;
}
}
self.servers.push(server2.clone());
}
}
pub fn get_first_peer_id(&self) -> Option<PubKey> {
self.servers.first().map(|s| s.peer_id)
}
pub fn get_domain(&self) -> Option<String> {
for server in self.servers.iter() {
if let BrokerServerTypeV0::Domain(name) = &server.server_type {
return Some(name.clone());
}
}
None
}
pub fn to_iframe_msgs(&self) -> Vec<BootstrapIframeMsg> {
self.servers.iter().map(|server| server.to_iframe_msg()).collect()
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum BootstrapContent {
V0(BootstrapContentV0),
}
impl BootstrapContent {
pub fn servers(&self) -> &Vec<BrokerServerV0> {
match self {
Self::V0(v0) => &v0.servers,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct LocalBootstrapInfoV0 {
pub bootstrap: BootstrapContentV0,
pub registration_url: Option<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum LocalBootstrapInfo {
V0(LocalBootstrapInfoV0),
}
impl LocalBootstrapInfo {
pub fn servers(&self) -> &Vec<BrokerServerV0> {
match self {
Self::V0(v0) => &v0.bootstrap.servers,
}
}
}
impl From<LocalBootstrapInfo> for Invitation {
fn from(value: LocalBootstrapInfo) -> Self {
let LocalBootstrapInfo::V0(info) = value;
let name = info.bootstrap.get_domain();
let url = info.registration_url.clone();
Invitation::V0(InvitationV0 {
bootstrap: info.bootstrap,
code: None,
name,
url,
})
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum InvitationCode {
Unique(SymKey),
Admin(SymKey),
Multi(SymKey),
Setup(SymKey),
}
impl InvitationCode {
pub fn get_symkey(&self) -> SymKey {
match self {
Self::Unique(s) | Self::Admin(s) | Self::Multi(s) | Self::Setup(s) => s.clone(),
}
}
}
impl fmt::Display for InvitationCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Unique(k) => write!(f, "unique {}", k),
Self::Admin(k) => write!(f, "admin {}", k),
Self::Multi(k) => write!(f, "multi {}", k),
Self::Setup(k) => write!(f, "setup {}", k),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct InvitationV0 {
pub bootstrap: BootstrapContentV0,
pub code: Option<SymKey>,
pub name: Option<String>,
pub url: Option<String>,
}
impl InvitationV0 {
pub fn set_bootstrap(&mut self, content: BootstrapContent) {
match content {
BootstrapContent::V0(v0) => self.bootstrap = v0,
}
}
pub fn empty(name: Option<String>) -> Self {
InvitationV0 {
bootstrap: BootstrapContentV0::new_empty(),
code: None,
name,
url: None,
}
}
pub fn new(
bootstrap_content: BootstrapContent,
code: Option<SymKey>,
name: Option<String>,
url: Option<String>,
) -> Self {
match bootstrap_content {
BootstrapContent::V0(v0) => InvitationV0 {
bootstrap: v0,
code,
name,
url,
},
}
}
pub fn append_bootstraps(&mut self, add: &mut Option<BootstrapContentV0>) {
if add.is_some() {
let add = add.as_mut().unwrap();
self.bootstrap.servers.append(&mut add.servers);
}
}
}
impl Invitation {
pub fn new_v0(
bootstrap: BootstrapContentV0,
name: Option<String>,
url: Option<String>,
) -> Self {
Invitation::V0(InvitationV0 {
bootstrap,
code: Some(SymKey::random()),
name,
url,
})
}
pub fn new_v0_free(
bootstrap: BootstrapContentV0,
name: Option<String>,
url: Option<String>,
) -> Self {
Invitation::V0(InvitationV0 {
bootstrap,
code: None,
name,
url,
})
}
pub fn intersects(&self, invite2: Invitation) -> Invitation {
let Invitation::V0(v0) = self;
let mut new_invite = InvitationV0 {
bootstrap: BootstrapContentV0::new_empty(),
code: v0.code.clone(),
name: v0.name.clone(),
url: v0.url.clone(),
};
for server2 in invite2.get_servers() {
for server1 in &v0.bootstrap.servers {
if *server1 == *server2 {
new_invite.bootstrap.servers.push(server2.clone());
break;
}
}
}
Invitation::V0(new_invite)
}
pub fn get_servers(&self) -> &Vec<BrokerServerV0> {
match self {
Invitation::V0(v0) => &v0.bootstrap.servers,
}
}
pub fn get_domain(&self) -> Option<String> {
for bootstrap in self.get_servers() {
let res = bootstrap.get_domain();
if res.is_some() {
return res;
}
}
None
}
pub fn set_name(&mut self, name: Option<String>) {
if name.is_some() {
match self {
Invitation::V0(v0) => v0.name = Some(name.unwrap()),
}
}
}
pub fn set_url(&mut self, url: Option<&String>) {
if url.is_some() {
match self {
Invitation::V0(v0) => v0.url = Some(url.unwrap().clone()),
}
}
}
pub fn get_urls(&self) -> Vec<String> {
match self {
Invitation::V0(v0) => {
let mut res = vec![];
let ser = serde_bare::to_vec(&self).unwrap();
let url_param = base64_url::encode(&ser);
res.push(format!("{}/#/i/{}", NG_NET_URL, url_param));
for server in &v0.bootstrap.servers {
match &server.server_type {
BrokerServerTypeV0::Domain(domain) => {
res.push(format!("https://{}/#/i/{}", domain, url_param));
}
BrokerServerTypeV0::BoxPrivate(addrs) => {
for bindaddr in addrs {
res.push(format!(
"http://{}:{}/#/i/{}",
bindaddr.ip, bindaddr.port, url_param
));
}
}
BrokerServerTypeV0::Localhost(port) => {
res.push(format!("{}/#/i/{}", local_http_url(&port), url_param));
}
_ => {}
}
}
res
}
}
}
}
impl fmt::Display for Invitation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let ser = serde_bare::to_vec(&self).unwrap();
let string = base64_url::encode(&ser);
write!(f, "{}", string)
}
}
impl TryFrom<String> for Invitation {
type Error = NgError;
fn try_from(value: String) -> Result<Self, NgError> {
let ser = base64_url::decode(&value).map_err(|_| NgError::InvalidInvitation)?;
let invite: Invitation =
serde_bare::from_slice(&ser).map_err(|_| NgError::InvalidInvitation)?;
Ok(invite)
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum Invitation {
V0(InvitationV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CreateAccountBSP {
V0(CreateAccountBSPV0),
}
impl TryFrom<String> for CreateAccountBSP {
type Error = NgError;
fn try_from(value: String) -> Result<Self, NgError> {
let ser = base64_url::decode(&value).map_err(|_| NgError::InvalidCreateAccount)?;
let invite: CreateAccountBSP =
serde_bare::from_slice(&ser).map_err(|_| NgError::InvalidCreateAccount)?;
Ok(invite)
}
}
impl CreateAccountBSP {
pub fn encode(&self) -> Option<String> {
let payload_ser = serde_bare::to_vec(self).ok();
if payload_ser.is_none() {
return None;
}
Some(base64_url::encode(&payload_ser.unwrap()))
}
pub fn redirect_url(&self) -> &Option<String> {
match self {
Self::V0(v0) => &v0.redirect_url,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CreateAccountBSPV0 {
pub redirect_url: Option<String>,
}
#[cfg(not(target_arch = "wasm32"))]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ListenerInfo {
pub config: ListenerV0,
pub addrs: Vec<BindAddress>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum AcceptForwardForV0 {
No,
PrivateDomain((String, String)),
PublicDomain((String, String)),
PublicDomainPeer((String, PrivKey, String)),
PublicDyn((u16, u32, String)),
PublicStatic((BindAddress, Option<BindAddress>, String)),
}
impl AcceptForwardForV0 {
pub fn get_public_bind_addresses(&self) -> Vec<BindAddress> {
match self {
AcceptForwardForV0::PublicStatic((ipv4, ipv6, _)) => {
let mut res = vec![ipv4.clone()];
if ipv6.is_some() {
res.push(ipv6.unwrap().clone())
}
res
}
AcceptForwardForV0::PublicDyn(_) => {
todo!();
}
_ => panic!("cannot call get_public_bind_addresses"),
}
}
pub fn get_public_bind_ipv6_address(&self) -> Option<IP> {
match self {
AcceptForwardForV0::PublicStatic((_ipv4, ipv6, _)) => {
if ipv6.is_some() {
return Some(ipv6.unwrap().ip.clone());
} else {
return None;
}
}
AcceptForwardForV0::PublicDyn(_) => {
todo!();
}
_ => None,
}
}
pub fn is_public_domain(&self) -> bool {
match self {
AcceptForwardForV0::PublicDomainPeer(_) => true,
AcceptForwardForV0::PublicDomain(_) => true,
_ => false,
}
}
pub fn is_public_static(&self) -> bool {
match self {
AcceptForwardForV0::PublicStatic(_) => true,
_ => false,
}
}
pub fn is_no(&self) -> bool {
match self {
AcceptForwardForV0::No => true,
_ => false,
}
}
pub fn is_public_dyn(&self) -> bool {
match self {
AcceptForwardForV0::PublicDyn(_) => true,
_ => false,
}
}
pub fn is_private_domain(&self) -> bool {
match self {
AcceptForwardForV0::PrivateDomain(_) => true,
_ => false,
}
}
pub fn domain_with_common_peer_id(&self) -> Option<PubKey> {
match self {
AcceptForwardForV0::PublicDomainPeer((_, privkey, _)) => Some(privkey.to_pub()),
_ => None,
}
}
pub fn get_domain(&self) -> &str {
let domain = get_domain_without_port_443(match self {
AcceptForwardForV0::PrivateDomain((d, _)) => d,
AcceptForwardForV0::PublicDomain((d, _)) => d,
AcceptForwardForV0::PublicDomainPeer((d, _, _)) => d,
_ => panic!("cannot call get_domain if AcceptForwardForV0 is not a domain"),
});
domain
}
}
#[cfg(not(target_arch = "wasm32"))]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ListenerV0 {
pub interface_name: String,
pub if_type: InterfaceType,
pub interface_refresh: u32,
pub ipv6: bool,
pub port: u16,
pub private_core: bool,
pub serve_app: bool,
pub bind_public_ipv6: bool,
pub refuse_clients: bool,
pub discoverable: bool,
pub accept_direct: bool,
pub accept_forward_for: AcceptForwardForV0,
}
#[cfg(not(target_arch = "wasm32"))]
impl ListenerV0 {
pub fn should_bind_public_ipv6_to_private_interface(&self, ip: Ipv6Addr) -> bool {
let public_ip = self.accept_forward_for.get_public_bind_ipv6_address();
if public_ip.is_none() {
return false;
}
let public_ipv6addr: IpAddr = public_ip.as_ref().unwrap().into();
return if let IpAddr::V6(v6) = public_ipv6addr {
self.bind_public_ipv6 && self.if_type == InterfaceType::Private && ip == v6
} else {
false
};
}
pub fn new_direct(interface: Interface, ipv6: bool, port: u16) -> Self {
Self {
interface_name: interface.name,
if_type: interface.if_type,
interface_refresh: 0,
ipv6,
port,
private_core: false,
discoverable: false,
accept_direct: true,
refuse_clients: false,
serve_app: true,
bind_public_ipv6: false,
accept_forward_for: AcceptForwardForV0::No,
}
}
pub fn is_core(&self) -> bool {
match self.accept_forward_for {
AcceptForwardForV0::PublicStatic(_) => true,
AcceptForwardForV0::PublicDyn(_) => true,
AcceptForwardForV0::PublicDomain(_) | AcceptForwardForV0::PublicDomainPeer(_) => false,
AcceptForwardForV0::PrivateDomain(_) => false,
AcceptForwardForV0::No => {
self.if_type == InterfaceType::Public
|| (self.private_core && self.if_type != InterfaceType::Invalid)
}
}
}
pub fn accepts_client(&self) -> bool {
match self.accept_forward_for {
AcceptForwardForV0::PublicStatic(_)
| AcceptForwardForV0::PublicDyn(_)
| AcceptForwardForV0::PublicDomain(_)
| AcceptForwardForV0::PublicDomainPeer(_) => self.accept_direct || !self.refuse_clients,
AcceptForwardForV0::PrivateDomain(_) => true,
AcceptForwardForV0::No => {
self.if_type == InterfaceType::Public && !self.refuse_clients
|| self.if_type != InterfaceType::Public
}
}
}
pub fn get_bootstraps(&self, addrs: Vec<BindAddress>) -> Vec<BrokerServerTypeV0> {
let mut res: Vec<BrokerServerTypeV0> = vec![];
match self.accept_forward_for {
AcceptForwardForV0::PublicStatic(_) => {
let pub_addrs = self.accept_forward_for.get_public_bind_addresses();
if !self.refuse_clients {
res.push(BrokerServerTypeV0::Public(pub_addrs));
}
if self.accept_direct {
res.push(BrokerServerTypeV0::BoxPrivate(addrs));
}
}
AcceptForwardForV0::PublicDyn(_) => {
let pub_addrs = self.accept_forward_for.get_public_bind_addresses();
if !self.refuse_clients {
res.push(BrokerServerTypeV0::BoxPublicDyn(pub_addrs));
}
if self.accept_direct {
res.push(BrokerServerTypeV0::BoxPrivate(addrs));
}
}
AcceptForwardForV0::PublicDomain(_) | AcceptForwardForV0::PublicDomainPeer(_) => {
if !self.refuse_clients {
res.push(BrokerServerTypeV0::Domain(
self.accept_forward_for.get_domain().to_string(),
));
}
}
AcceptForwardForV0::PrivateDomain(_) => {
res.push(BrokerServerTypeV0::Domain(
self.accept_forward_for.get_domain().to_string(),
));
}
AcceptForwardForV0::No => {
if self.if_type == InterfaceType::Loopback {
res.push(BrokerServerTypeV0::Localhost(addrs[0].port));
} else if self.if_type == InterfaceType::Public {
if !self.refuse_clients {
res.push(BrokerServerTypeV0::Public(addrs));
}
} else if self.if_type == InterfaceType::Private {
res.push(BrokerServerTypeV0::BoxPrivate(addrs));
}
}
}
res
}
}
#[cfg(not(target_arch = "wasm32"))]
impl fmt::Display for ListenerV0 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut id = self.interface_name.clone();
id.push('@');
id.push_str(&self.port.to_string());
write!(f, "{}", id)
}
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum BrokerOverlayPermission {
Nobody,
Anybody,
AllRegisteredUser,
UsersList(Vec<UserId>),
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct BrokerOverlayConfigV0 {
pub overlays: Vec<OverlayId>,
pub core: BrokerOverlayPermission,
pub server: BrokerOverlayPermission,
pub allow_read: bool,
pub forward: Vec<BrokerServerV0>,
}
impl BrokerOverlayConfigV0 {
pub fn new() -> Self {
BrokerOverlayConfigV0 {
overlays: vec![],
core: BrokerOverlayPermission::Nobody,
server: BrokerOverlayPermission::Nobody,
allow_read: false,
forward: vec![],
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum RegistrationConfig {
Closed,
Invitation,
Open,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum OverlayAccess {
ReadOnly(OverlayId),
ReadWrite((OverlayId, OverlayId)),
WriteOnly(OverlayId),
}
impl OverlayAccess {
pub fn is_read_only(&self) -> bool {
match self {
Self::ReadOnly(_) => true,
_ => false,
}
}
pub fn new_write_access_from_store(store: &Store) -> OverlayAccess {
match store.get_store_repo() {
StoreRepo::V0(StoreRepoV0::PrivateStore(_)) | StoreRepo::V0(StoreRepoV0::Dialog(_)) => {
OverlayAccess::WriteOnly(store.inner_overlay())
}
StoreRepo::V0(StoreRepoV0::ProtectedStore(_))
| StoreRepo::V0(StoreRepoV0::Group(_))
| StoreRepo::V0(StoreRepoV0::PublicStore(_)) => {
OverlayAccess::ReadWrite((store.inner_overlay(), store.outer_overlay()))
}
}
}
pub fn new_read_access_from_store(store: &Store) -> OverlayAccess {
match store.get_store_repo() {
StoreRepo::V0(StoreRepoV0::PrivateStore(_)) | StoreRepo::V0(StoreRepoV0::Dialog(_)) => {
panic!("cannot get read access to a private or dialog store");
}
StoreRepo::V0(StoreRepoV0::ProtectedStore(_))
| StoreRepo::V0(StoreRepoV0::Group(_))
| StoreRepo::V0(StoreRepoV0::PublicStore(_)) => {
OverlayAccess::ReadOnly(store.outer_overlay())
}
}
}
pub fn new_ro(outer_overlay: OverlayId) -> Result<Self, NgError> {
if let OverlayId::Outer(_digest) = outer_overlay {
Ok(OverlayAccess::ReadOnly(outer_overlay))
} else {
Err(NgError::InvalidArgument)
}
}
pub fn new_rw(inner_overlay: OverlayId, outer_overlay: OverlayId) -> Result<Self, NgError> {
if let OverlayId::Inner(_digest) = inner_overlay {
if let OverlayId::Outer(_digest) = outer_overlay {
Ok(OverlayAccess::ReadWrite((inner_overlay, outer_overlay)))
} else {
Err(NgError::InvalidArgument)
}
} else {
Err(NgError::InvalidArgument)
}
}
pub fn new_wo(inner_overlay: OverlayId) -> Result<Self, NgError> {
if let OverlayId::Inner(_digest) = inner_overlay {
Ok(OverlayAccess::WriteOnly(inner_overlay))
} else {
Err(NgError::InvalidArgument)
}
}
pub fn overlay_id_for_client_protocol_purpose(&self) -> &OverlayId {
match self {
Self::ReadOnly(ro) => ro,
Self::ReadWrite((inner, _outer)) => inner,
Self::WriteOnly(wo) => wo,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct InnerOverlayLink {
pub id: StoreOverlay,
pub store_overlay_readcap: ReadCap,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum OverlayLink {
Outer(Digest),
InnerLink(InnerOverlayLink),
Inner(Digest),
Inherit,
Public(PubKey),
Global,
}
impl OverlayLink {
pub fn is_outer(&self) -> bool {
match self {
Self::Outer(_) => true,
_ => false,
}
}
pub fn outer(&self) -> &Digest {
match self {
Self::Outer(o) => o,
_ => panic!("not an outer overlay ID"),
}
}
}
impl TryFrom<OverlayLink> for OverlayId {
type Error = NgError;
fn try_from(link: OverlayLink) -> Result<Self, Self::Error> {
Ok(match link {
OverlayLink::Inner(Digest::Blake3Digest32(i)) => OverlayId::Inner(i),
OverlayLink::Outer(Digest::Blake3Digest32(i)) => OverlayId::Outer(i),
OverlayLink::Global => OverlayId::Global,
_ => return Err(NgError::InvalidArgument),
})
}
}
impl From<OverlayId> for OverlayLink {
fn from(id: OverlayId) -> Self {
match id {
OverlayId::Inner(i) => OverlayLink::Inner(Digest::from_slice(i)),
OverlayId::Outer(o) => OverlayLink::Outer(Digest::from_slice(o)),
OverlayId::Global => OverlayLink::Global,
}
}
}
pub type SessionId = PubKey;
pub type ClientId = PubKey;
pub type IPv4 = [u8; 4];
const LOOPBACK_IPV4: IP = IP::IPv4([127, 0, 0, 1]);
pub type IPv6 = [u8; 16];
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum IP {
IPv4(IPv4),
IPv6(IPv6),
}
impl IP {
pub fn is_public(&self) -> bool {
is_public_ip(&self.into())
}
pub fn is_private(&self) -> bool {
is_private_ip(&self.into())
}
pub fn is_loopback(&self) -> bool {
let t: &IpAddr = &self.into();
t.is_loopback()
}
pub fn is_v6(&self) -> bool {
if let Self::IPv6(_) = self {
true
} else {
false
}
}
pub fn is_v4(&self) -> bool {
if let Self::IPv4(_) = self {
true
} else {
false
}
}
}
impl fmt::Display for IP {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let t: IpAddr = self.try_into().unwrap();
match self {
IP::IPv4(_) => write!(f, "{}", t),
IP::IPv6(_) => write!(f, "[{}]", t),
}
}
}
impl From<&IpAddr> for IP {
#[inline]
fn from(ip: &IpAddr) -> IP {
match ip {
IpAddr::V4(v4) => IP::IPv4(v4.octets()),
IpAddr::V6(v6) => IP::IPv6(v6.octets()),
}
}
}
impl From<&IP> for IpAddr {
#[inline]
fn from(ip: &IP) -> IpAddr {
match ip {
IP::IPv4(v4) => IpAddr::from(*v4),
IP::IPv6(v6) => IpAddr::from(*v6),
}
}
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum TransportProtocol {
WS,
QUIC,
Local,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct IPTransportAddr {
pub ip: IP,
pub port: u16,
pub protocol: TransportProtocol,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum NetAddr {
IPTransport(IPTransportAddr),
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum ClientType {
Web,
NativeIos,
NativeAndroid,
NativeMacOS,
NativeLinux,
NativeWin,
NativeService,
NodeService,
Verifier,
VerifierLocal,
Box, Stick, WalletMaster,
ClientBroker,
Cli,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct ClientInfoV0 {
pub client_type: ClientType,
pub details: String,
pub version: String,
pub timestamp_install: u64,
pub timestamp_updated: u64,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum ClientInfo {
V0(ClientInfoV0),
}
impl ClientInfo {
pub fn new(client_type: ClientType, details: String, version: String) -> ClientInfo {
let timestamp_install = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs();
ClientInfo::V0(ClientInfoV0 {
details,
version,
client_type,
timestamp_install,
timestamp_updated: timestamp_install,
})
}
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum OverlayLeave {
V0(),
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct PublisherAdvertContentV0 {
pub topic: TopicId,
pub peer: DirectPeerId,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct PublisherAdvertV0 {
pub content: PublisherAdvertContentV0,
pub sig: Sig,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum PublisherAdvert {
V0(PublisherAdvertV0),
}
impl PublisherAdvert {
pub fn new(
topic_id: TopicId,
topic_key: BranchWriteCapSecret,
broker_peer: DirectPeerId,
) -> PublisherAdvert {
let content = PublisherAdvertContentV0 {
peer: broker_peer,
topic: topic_id,
};
let content_ser = serde_bare::to_vec(&content).unwrap();
let sig = sign(&topic_key, &topic_id, &content_ser).unwrap();
PublisherAdvert::V0(PublisherAdvertV0 { content, sig })
}
pub fn topic_id(&self) -> &TopicId {
match self {
Self::V0(v0) => &v0.content.topic,
}
}
pub fn verify(&self) -> Result<(), NgError> {
match self {
Self::V0(v0) => verify(
&serde_bare::to_vec(&v0.content).unwrap(),
v0.sig,
v0.content.topic,
),
}
}
pub fn verify_for_broker(&self, peer_id: &DirectPeerId) -> Result<(), ProtocolError> {
match self {
Self::V0(v0) => {
if v0.content.peer != *peer_id {
return Err(ProtocolError::InvalidPublisherAdvert);
}
}
}
Ok(self.verify()?)
}
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct SubReqV0 {
pub topic: TopicId,
pub publisher: Option<DirectPeerId>,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum SubReq {
V0(SubReqV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SubMarkerV0 {
pub publisher: DirectPeerId,
pub topic: TopicId,
pub subscriber: DirectPeerId,
pub known_heads: Vec<ObjectId>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum SubMarker {
V0(SubMarkerV0),
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct UnsubReqV0 {
pub topic: TopicId,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum UnsubReq {
V0(UnsubReqV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BlockSearchTopicV0 {
pub topic: TopicId,
pub search_in_subs: bool,
pub ids: Vec<ObjectId>,
pub include_children: bool,
pub path: Vec<PeerId>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum BlockSearchTopic {
V0(BlockSearchTopicV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BlockSearchRandomV0 {
pub ids: Vec<BlockId>,
pub include_children: bool,
pub path: Vec<DirectPeerId>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum BlockSearchRandom {
V0(BlockSearchRandomV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BlockResultV0 {
pub payload: Vec<Block>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum BlockResult {
V0(BlockResultV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TopicSyncReqV0 {
pub topic: TopicId,
pub known_heads: Vec<ObjectId>,
pub target_heads: Vec<ObjectId>,
pub known_commits: Option<BloomFilter>,
#[serde(skip)]
pub overlay: Option<OverlayId>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum TopicSyncReq {
V0(TopicSyncReqV0),
}
impl TopicSyncReq {
pub fn overlay(&self) -> &OverlayId {
match self {
Self::V0(v0) => v0.overlay.as_ref().unwrap(),
}
}
pub fn set_overlay(&mut self, overlay: OverlayId) {
match self {
Self::V0(v0) => v0.overlay = Some(overlay),
}
}
pub fn topic(&self) -> &TopicId {
match self {
TopicSyncReq::V0(o) => &o.topic,
}
}
pub fn known_heads(&self) -> &Vec<ObjectId> {
match self {
TopicSyncReq::V0(o) => &o.known_heads,
}
}
pub fn target_heads(&self) -> &Vec<ObjectId> {
match self {
TopicSyncReq::V0(o) => &o.target_heads,
}
}
pub fn known_commits(&self) -> &Option<BloomFilter> {
match self {
TopicSyncReq::V0(o) => &o.known_commits,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum PeerStatus {
Connected,
Disconnected,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ForwardedPeerAdvertV0 {
pub peer_advert: PeerAdvertV0,
pub user_hash: Digest,
pub status: PeerStatus,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ForwardedPeerAdvert {
V0(ForwardedPeerAdvertV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ForwardedPeerConflictV0 {
pub advert_1: ForwardedPeerAdvertV0,
pub advert_2: ForwardedPeerAdvertV0,
pub error_code: u16,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ForwardedPeerConflict {
V0(ForwardedPeerConflictV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PeerAdvertContentV0 {
pub peer: PeerId,
pub forwarded_by: Option<DirectPeerId>,
pub address: Vec<NetAddr>,
pub version: u32,
#[serde(with = "serde_bytes")]
pub metadata: Vec<u8>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PeerAdvertV0 {
pub content: PeerAdvertContentV0,
pub sig: Sig,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum PeerAdvert {
V0(PeerAdvertV0),
}
impl PeerAdvert {
pub fn version(&self) -> u32 {
match self {
PeerAdvert::V0(o) => o.content.version,
}
}
pub fn peer(&self) -> &PeerId {
match self {
PeerAdvert::V0(o) => &o.content.peer,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum InnerOverlayMessageContentV0 {
OverlayLeave(OverlayLeave),
ForwardedPeerAdvert(ForwardedPeerAdvert),
ForwardedPeerConflict(ForwardedPeerConflict),
PublisherJoined(PublisherAdvert),
PublisherLeft(PublisherAdvert),
SubReq(SubReq),
SubMarker(SubMarker),
UnsubReq(UnsubReq),
Event(Event),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct InnerOverlayMessagePayloadV0 {
pub seq: u64,
pub content: InnerOverlayMessageContentV0,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct InnerOverlayMessageV0 {
pub session: SessionId,
pub payload: InnerOverlayMessagePayloadV0,
pub sig: Sig,
#[serde(with = "serde_bytes")]
pub padding: Vec<u8>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum InnerOverlayMessage {
V0(InnerOverlayMessageV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct OverlayAdvertPayloadV0 {
pub overlay: OverlayId,
pub session: SessionId,
pub seq: u64,
pub publishers: Vec<PublisherAdvert>,
pub previous_session: Option<SessionId>,
pub peer: DirectPeerId,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct OverlayAdvertV0 {
pub payload: OverlayAdvertPayloadV0,
pub sig: Sig,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum OverlayAdvert {
V0(OverlayAdvertV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CoreBrokerJoinedAdvertV0 {
pub overlays: Vec<OverlayAdvertV0>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CoreBrokerLeftAdvertV0 {
pub disconnected: DirectPeerId,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CoreOverlayJoinedAdvertV0 {
pub overlay: OverlayAdvertV0,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreBrokerJoinedAdvert {
V0(CoreBrokerJoinedAdvertV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreBrokerLeftAdvert {
V0(CoreBrokerLeftAdvertV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreOverlayJoinedAdvert {
V0(CoreOverlayJoinedAdvertV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreAdvertContentV0 {
BrokerJoined(CoreBrokerJoinedAdvert),
BrokerLeft(CoreBrokerLeftAdvert),
OverlayJoined(CoreOverlayJoinedAdvert),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CoreAdvertV0 {
pub content: CoreAdvertContentV0,
pub path: Vec<DirectPeerId>,
pub sig: Sig,
#[serde(with = "serde_bytes")]
pub padding: Vec<u8>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct OverlayAdvertMarkerV0 {
pub marker: OverlayAdvertV0,
pub in_reply_to: SessionId,
pub path: Vec<DirectPeerId>,
pub reply_nonce: u64,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CoreBlocksGetV0 {
pub ids: Vec<BlockId>,
pub include_children: bool,
pub req_nonce: u64,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CoreBlockResultV0 {
pub payload: Vec<Block>,
pub req_nonce: u64,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ReturnPathTimingAdvertV0 {
pub sig: Sig,
pub nonce: u64,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum OverlayAdvertMarker {
V0(OverlayAdvertMarkerV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ReturnPathTimingAdvert {
V0(ReturnPathTimingAdvertV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreBlocksGet {
V0(CoreBlocksGetV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreBlockResult {
V0(CoreBlockResultV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreDirectMessageContentV0 {
OverlayAdvertMarker(OverlayAdvertMarker),
ReturnPathTimingAdvert(ReturnPathTimingAdvert),
BlocksGet(CoreBlocksGet),
BlockResult(CoreBlockResult),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CoreDirectMessageV0 {
pub content: CoreDirectMessageContentV0,
pub reverse_path: Vec<DirectPeerId>,
pub from: DirectPeerId,
pub sig: Sig,
#[serde(with = "serde_bytes")]
pub padding: Vec<u8>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CoreBrokerConnectV0 {
pub inner_overlays: Vec<OverlayAdvertV0>,
pub outer_overlays: Vec<Digest>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreBrokerConnect {
V0(CoreBrokerConnectV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreBrokerConnectResponse {
V0(CoreBrokerConnectResponseV0),
}
impl CoreBrokerConnect {
pub fn core_message(&self, id: i64) -> CoreMessage {
match self {
CoreBrokerConnect::V0(v0) => {
CoreMessage::V0(CoreMessageV0::Request(CoreRequest::V0(CoreRequestV0 {
padding: vec![],
id,
content: CoreRequestContentV0::BrokerConnect(CoreBrokerConnect::V0(v0.clone())),
})))
}
}
}
}
pub type CoreBrokerDisconnectV0 = ();
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreOverlayJoinV0 {
Inner(OverlayAdvert),
Outer(Digest),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum OuterOverlayResponseContentV0 {
EmptyResponse(()),
Block(Block),
TopicSyncRes(TopicSyncRes),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum OuterOverlayRequestContentV0 {
TopicSyncReq(TopicSyncReq),
OverlayLeave(OverlayLeave),
TopicSub(PubKey),
TopicUnsub(PubKey),
BlocksGet(BlocksGet),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct OuterOverlayRequestV0 {
pub overlay: Digest,
pub content: OuterOverlayRequestContentV0,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct OuterOverlayResponseV0 {
pub overlay: Digest,
pub content: OuterOverlayResponseContentV0,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CoreTopicSyncReqV0 {
pub topic: TopicId,
pub search_in_subs: bool,
pub known_heads: Vec<ObjectId>,
pub target_heads: Vec<ObjectId>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreTopicSyncReq {
V0(CoreTopicSyncReqV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum TopicSyncResV0 {
Event(Event),
Block(Block),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum TopicSyncRes {
V0(TopicSyncResV0),
}
impl TopicSyncRes {
pub fn event(&self) -> &Event {
match self {
Self::V0(TopicSyncResV0::Event(e)) => e,
_ => panic!("this TopicSyncResV0 is not an event"),
}
}
}
impl fmt::Display for TopicSyncRes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::V0(v0) => match v0 {
TopicSyncResV0::Event(e) => writeln!(f, "====== Event ====== {e}"),
TopicSyncResV0::Block(b) => writeln!(f, "====== Block ID ====== {}", b.id()),
},
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreBrokerDisconnect {
V0(CoreBrokerDisconnectV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreOverlayJoin {
V0(CoreOverlayJoinV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum OuterOverlayRequest {
V0(OuterOverlayRequestV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreRequestContentV0 {
BrokerConnect(CoreBrokerConnect),
BrokerDisconnect(CoreBrokerDisconnect),
OverlayJoin(CoreOverlayJoin),
BlockSearchTopic(BlockSearchTopic),
BlockSearchRandom(BlockSearchRandom),
TopicSyncReq(CoreTopicSyncReq),
OuterOverlayRequest(OuterOverlayRequest),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CoreRequestV0 {
pub id: i64,
pub content: CoreRequestContentV0,
#[serde(with = "serde_bytes")]
pub padding: Vec<u8>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreRequest {
V0(CoreRequestV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CoreBrokerConnectResponseV0 {
pub successes: Vec<OverlayId>,
pub errors: Vec<OverlayId>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum OuterOverlayResponse {
V0(OuterOverlayResponseV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreResponseContentV0 {
BrokerConnectResponse(CoreBrokerConnectResponse),
BlockResult(BlockResult),
TopicSyncRes(TopicSyncRes),
OuterOverlayResponse(OuterOverlayResponse),
EmptyResponse(()),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CoreResponseV0 {
pub id: i64,
pub result: u16,
pub content: CoreResponseContentV0,
#[serde(with = "serde_bytes")]
pub padding: Vec<u8>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreResponse {
V0(CoreResponseV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum OuterOverlayMessageContentV0 {
Event(Event),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct OuterOverlayMessageV0 {
pub overlay: Digest,
pub content: OuterOverlayMessageContentV0,
#[serde(with = "serde_bytes")]
pub padding: Vec<u8>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreAdvert {
V0(CoreAdvertV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreDirectMessage {
V0(CoreDirectMessageV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum OuterOverlayMessage {
V0(OuterOverlayMessageV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreMessageV0 {
Request(CoreRequest),
Response(CoreResponse),
Advert(CoreAdvert),
Direct(CoreDirectMessage),
InnerOverlay(InnerOverlayMessage),
OuterOverlay(OuterOverlayMessage),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CoreMessage {
V0(CoreMessageV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AppMessageContentV0 {
Request(AppRequest),
Response(AppResponse),
SessionStop(AppSessionStop),
SessionStart(AppSessionStart),
EmptyResponse,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AppMessageV0 {
pub content: AppMessageContentV0,
pub id: i64,
pub result: u16,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AppMessage {
V0(AppMessageV0),
}
impl IStreamable for AppMessage {
fn result(&self) -> u16 {
match self {
AppMessage::V0(v0) => v0.result,
}
}
fn set_result(&mut self, result: u16) {
match self {
AppMessage::V0(v0) => v0.result = result,
}
}
}
impl AppMessage {
pub fn get_actor(&self) -> Box<dyn EActor> {
match self {
AppMessage::V0(AppMessageV0 { content: o, id, .. }) => match o {
AppMessageContentV0::Request(req) => req.get_actor(*id),
AppMessageContentV0::SessionStop(req) => req.get_actor(*id),
AppMessageContentV0::SessionStart(req) => req.get_actor(*id),
AppMessageContentV0::Response(_) | AppMessageContentV0::EmptyResponse => {
panic!("it is not a request");
}
},
}
}
pub fn id(&self) -> Option<i64> {
match self {
AppMessage::V0(v0) => Some(v0.id),
}
}
pub fn set_id(&mut self, id: i64) {
match self {
AppMessage::V0(r) => r.id = id,
}
}
}
impl From<AppMessage> for ProtocolMessage {
fn from(msg: AppMessage) -> ProtocolMessage {
ProtocolMessage::AppMessage(msg)
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AdminRequestContentV0 {
AddUser(AddUser),
DelUser(DelUser),
ListUsers(ListUsers),
ListInvitations(ListInvitations),
AddInvitation(AddInvitation),
#[doc(hidden)]
CreateUser(CreateUser),
}
impl AdminRequestContentV0 {
pub fn type_id(&self) -> TypeId {
match self {
Self::AddUser(a) => a.type_id(),
Self::DelUser(a) => a.type_id(),
Self::ListUsers(a) => a.type_id(),
Self::ListInvitations(a) => a.type_id(),
Self::AddInvitation(a) => a.type_id(),
Self::CreateUser(a) => a.type_id(),
}
}
pub fn get_actor(&self) -> Box<dyn EActor> {
match self {
Self::AddUser(a) => a.get_actor(),
Self::DelUser(a) => a.get_actor(),
Self::ListUsers(a) => a.get_actor(),
Self::ListInvitations(a) => a.get_actor(),
Self::AddInvitation(a) => a.get_actor(),
Self::CreateUser(a) => a.get_actor(),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AdminRequestV0 {
pub id: i64,
pub content: AdminRequestContentV0,
pub sig: Sig,
pub admin_user: PubKey,
#[serde(with = "serde_bytes")]
pub padding: Vec<u8>,
}
impl AdminRequestV0 {
pub fn get_actor(&self) -> Box<dyn EActor> {
self.content.get_actor()
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AdminRequest {
V0(AdminRequestV0),
}
impl AdminRequest {
pub fn id(&self) -> i64 {
match self {
Self::V0(o) => o.id,
}
}
pub fn set_id(&mut self, id: i64) {
match self {
Self::V0(v0) => {
v0.id = id;
}
}
}
pub fn type_id(&self) -> TypeId {
match self {
Self::V0(o) => o.content.type_id(),
}
}
pub fn sig(&self) -> Sig {
match self {
Self::V0(o) => o.sig,
}
}
pub fn admin_user(&self) -> PubKey {
match self {
Self::V0(o) => o.admin_user,
}
}
pub fn get_actor(&self) -> Box<dyn EActor> {
match self {
Self::V0(a) => a.get_actor(),
}
}
}
impl From<AdminRequest> for ProtocolMessage {
fn from(msg: AdminRequest) -> ProtocolMessage {
ProtocolMessage::Start(StartProtocol::Admin(msg))
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AdminResponseContentV0 {
EmptyResponse,
Users(Vec<PubKey>),
Invitations(Vec<(InvitationCode, u32, Option<String>)>),
Invitation(Invitation),
UserId(UserId),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AdminResponseV0 {
pub id: i64,
pub result: u16,
pub content: AdminResponseContentV0,
#[serde(with = "serde_bytes")]
pub padding: Vec<u8>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AdminResponse {
V0(AdminResponseV0),
}
impl From<Result<(), ProtocolError>> for AdminResponseV0 {
fn from(res: Result<(), ProtocolError>) -> AdminResponseV0 {
AdminResponseV0 {
id: 0,
result: res.map(|_| 0).unwrap_or_else(|e| e.into()),
content: AdminResponseContentV0::EmptyResponse,
padding: vec![],
}
}
}
impl From<Result<PubKey, ProtocolError>> for AdminResponseV0 {
fn from(res: Result<PubKey, ProtocolError>) -> AdminResponseV0 {
match res {
Err(e) => AdminResponseV0 {
id: 0,
result: e.into(),
content: AdminResponseContentV0::EmptyResponse,
padding: vec![],
},
Ok(id) => AdminResponseV0 {
id: 0,
result: 0,
content: AdminResponseContentV0::UserId(id),
padding: vec![],
},
}
}
}
impl From<Result<Vec<PubKey>, ProtocolError>> for AdminResponseV0 {
fn from(res: Result<Vec<PubKey>, ProtocolError>) -> AdminResponseV0 {
match res {
Err(e) => AdminResponseV0 {
id: 0,
result: e.into(),
content: AdminResponseContentV0::EmptyResponse,
padding: vec![],
},
Ok(vec) => AdminResponseV0 {
id: 0,
result: 0,
content: AdminResponseContentV0::Users(vec),
padding: vec![],
},
}
}
}
impl From<AdminResponseV0> for ProtocolMessage {
fn from(msg: AdminResponseV0) -> ProtocolMessage {
ProtocolMessage::AdminResponse(AdminResponse::V0(msg))
}
}
impl From<AdminResponse> for ProtocolMessage {
fn from(msg: AdminResponse) -> ProtocolMessage {
ProtocolMessage::AdminResponse(msg)
}
}
impl TryFrom<ProtocolMessage> for AdminResponse {
type Error = ProtocolError;
fn try_from(msg: ProtocolMessage) -> Result<Self, Self::Error> {
if let ProtocolMessage::AdminResponse(res) = msg {
Ok(res)
} else {
Err(ProtocolError::InvalidValue)
}
}
}
impl AdminResponse {
pub fn id(&self) -> i64 {
match self {
Self::V0(o) => o.id,
}
}
pub fn set_id(&mut self, id: i64) {
match self {
Self::V0(v0) => {
v0.id = id;
}
}
}
pub fn result(&self) -> u16 {
match self {
Self::V0(o) => o.result,
}
}
pub fn content_v0(&self) -> AdminResponseContentV0 {
match self {
Self::V0(o) => o.content.clone(),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct OpenRepoV0 {
pub hash: RepoHash,
pub overlay: OverlayAccess,
pub peers: Vec<PeerAdvert>,
pub max_peer_count: u16,
pub ro_topics: Vec<TopicId>,
pub rw_topics: Vec<PublisherAdvert>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum OpenRepo {
V0(OpenRepoV0),
}
impl OpenRepo {
pub fn peers(&self) -> &Vec<PeerAdvert> {
match self {
OpenRepo::V0(o) => &o.peers,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PinRepoV0 {
pub hash: RepoHash,
pub overlay: OverlayAccess,
pub overlay_root_topic: Option<TopicId>,
pub expose_outer: bool,
pub peers: Vec<PeerAdvert>,
pub max_peer_count: u16,
pub ro_topics: Vec<TopicId>,
pub rw_topics: Vec<PublisherAdvert>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum PinRepo {
V0(PinRepoV0),
}
impl PinRepo {
pub fn peers(&self) -> &Vec<PeerAdvert> {
match self {
PinRepo::V0(o) => &o.peers,
}
}
pub fn hash(&self) -> &RepoHash {
match self {
PinRepo::V0(o) => &o.hash,
}
}
pub fn ro_topics(&self) -> &Vec<TopicId> {
match self {
PinRepo::V0(o) => &o.ro_topics,
}
}
pub fn rw_topics(&self) -> &Vec<PublisherAdvert> {
match self {
PinRepo::V0(o) => &o.rw_topics,
}
}
pub fn overlay(&self) -> &OverlayId {
match self {
PinRepo::V0(o) => &o.overlay.overlay_id_for_client_protocol_purpose(),
}
}
pub fn overlay_access(&self) -> &OverlayAccess {
match self {
PinRepo::V0(o) => &o.overlay,
}
}
pub fn overlay_root_topic(&self) -> &Option<TopicId> {
match self {
PinRepo::V0(o) => &o.overlay_root_topic,
}
}
pub fn expose_outer(&self) -> bool {
match self {
PinRepo::V0(o) => o.expose_outer,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RefreshPinRepoV0 {
pub pin: PinRepo,
pub ban_member: Option<Digest>,
pub flush_topics: Vec<(TopicId, Sig)>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum RefreshPinRepo {
V0(RefreshPinRepoV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct UnpinRepoV0 {
pub hash: RepoHash,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum UnpinRepo {
V0(UnpinRepoV0),
}
impl UnpinRepo {
pub fn hash(&self) -> &RepoHash {
match self {
UnpinRepo::V0(o) => &o.hash,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RepoPinStatusReqV0 {
pub hash: RepoHash,
#[serde(skip)]
pub overlay: Option<OverlayId>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum RepoPinStatusReq {
V0(RepoPinStatusReqV0),
}
impl RepoPinStatusReq {
pub fn hash(&self) -> &RepoHash {
match self {
RepoPinStatusReq::V0(o) => &o.hash,
}
}
pub fn set_overlay(&mut self, overlay: OverlayId) {
match self {
Self::V0(v0) => v0.overlay = Some(overlay),
}
}
pub fn overlay(&self) -> &OverlayId {
match self {
Self::V0(v0) => v0.overlay.as_ref().unwrap(),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RepoPinStatusV0 {
pub hash: RepoHash,
pub expose_outer: bool,
pub topics: Vec<TopicSubRes>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum RepoPinStatus {
V0(RepoPinStatusV0),
}
impl RepoPinStatus {
pub fn hash(&self) -> &RepoHash {
match self {
RepoPinStatus::V0(o) => &o.hash,
}
}
pub fn is_topic_subscribed_as_publisher(&self, topic: &TopicId) -> bool {
match self {
Self::V0(v0) => {
for sub in &v0.topics {
if sub.topic_id() == topic {
return sub.is_publisher();
}
}
false
}
}
}
pub fn topics(&self) -> &Vec<TopicSubRes> {
match self {
Self::V0(v0) => &v0.topics,
}
}
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct TopicSubV0 {
pub topic: TopicId,
pub repo_hash: RepoHash,
pub publisher: Option<PublisherAdvert>,
#[serde(skip)]
pub overlay: Option<OverlayId>,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum TopicSub {
V0(TopicSubV0),
}
impl TopicSub {
pub fn hash(&self) -> &RepoHash {
match self {
Self::V0(o) => &o.repo_hash,
}
}
pub fn topic(&self) -> &TopicId {
match self {
Self::V0(o) => &o.topic,
}
}
pub fn publisher(&self) -> Option<&PublisherAdvert> {
match self {
Self::V0(o) => o.publisher.as_ref(),
}
}
pub fn set_overlay(&mut self, overlay: OverlayId) {
match self {
Self::V0(v0) => v0.overlay = Some(overlay),
}
}
pub fn overlay(&self) -> &OverlayId {
match self {
Self::V0(v0) => v0.overlay.as_ref().unwrap(),
}
}
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct TopicUnsubV0 {
pub topic: PubKey,
pub repo_hash: RepoHash,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum TopicUnsub {
V0(TopicUnsubV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BlocksGetV0 {
pub ids: Vec<BlockId>,
pub include_children: bool,
pub topic: Option<TopicId>,
#[serde(skip)]
pub overlay: Option<OverlayId>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum BlocksGet {
V0(BlocksGetV0),
}
impl BlocksGet {
pub fn ids(&self) -> &Vec<BlockId> {
match self {
BlocksGet::V0(o) => &o.ids,
}
}
pub fn include_children(&self) -> bool {
match self {
BlocksGet::V0(o) => o.include_children,
}
}
pub fn topic(&self) -> Option<PubKey> {
match self {
BlocksGet::V0(o) => o.topic,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CommitGetV0 {
pub id: ObjectId,
pub topic: Option<TopicId>,
#[serde(skip)]
pub overlay: Option<OverlayId>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CommitGet {
V0(CommitGetV0),
}
impl CommitGet {
pub fn id(&self) -> &ObjectId {
match self {
CommitGet::V0(o) => &o.id,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct WalletPutExportV0 {
pub wallet: ExportedWallet,
pub rendezvous_id: SymKey,
pub is_rendezvous: bool,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum WalletPutExport {
V0(WalletPutExportV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BlocksPutV0 {
pub blocks: Vec<Block>,
#[serde(skip)]
pub overlay: Option<OverlayId>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum BlocksPut {
V0(BlocksPutV0),
}
impl BlocksPut {
pub fn blocks(&self) -> &Vec<Block> {
match self {
BlocksPut::V0(o) => &o.blocks,
}
}
pub fn overlay(&self) -> &OverlayId {
match self {
Self::V0(v0) => v0.overlay.as_ref().unwrap(),
}
}
pub fn set_overlay(&mut self, overlay: OverlayId) {
match self {
Self::V0(v0) => v0.overlay = Some(overlay),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BlocksExistV0 {
pub blocks: Vec<BlockId>,
#[serde(skip)]
pub overlay: Option<OverlayId>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum BlocksExist {
V0(BlocksExistV0),
}
impl BlocksExist {
pub fn blocks(&self) -> &Vec<BlockId> {
match self {
BlocksExist::V0(o) => &o.blocks,
}
}
pub fn overlay(&self) -> &OverlayId {
match self {
Self::V0(v0) => v0.overlay.as_ref().unwrap(),
}
}
pub fn set_overlay(&mut self, overlay: OverlayId) {
match self {
Self::V0(v0) => v0.overlay = Some(overlay),
}
}
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct ObjectPinV0 {
pub id: ObjectId,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum ObjectPin {
V0(ObjectPinV0),
}
impl ObjectPin {
pub fn id(&self) -> ObjectId {
match self {
ObjectPin::V0(o) => o.id,
}
}
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct ObjectUnpinV0 {
pub id: ObjectId,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum ObjectUnpin {
V0(ObjectUnpinV0),
}
impl ObjectUnpin {
pub fn id(&self) -> ObjectId {
match self {
ObjectUnpin::V0(o) => o.id,
}
}
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct ObjectDelV0 {
pub id: ObjectId,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum ObjectDel {
V0(ObjectDelV0),
}
impl ObjectDel {
pub fn id(&self) -> ObjectId {
match self {
ObjectDel::V0(o) => o.id,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PublishEvent(pub Event, #[serde(skip)] pub Option<OverlayId>);
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ClientRequestContentV0 {
OpenRepo(OpenRepo),
PinRepo(PinRepo),
UnpinRepo(UnpinRepo),
RepoPinStatusReq(RepoPinStatusReq),
TopicSub(TopicSub),
TopicUnsub(TopicUnsub),
BlocksExist(BlocksExist),
BlocksGet(BlocksGet),
CommitGet(CommitGet),
TopicSyncReq(TopicSyncReq),
ObjectPin(ObjectPin),
ObjectUnpin(ObjectUnpin),
ObjectDel(ObjectDel),
BlocksPut(BlocksPut),
PublishEvent(PublishEvent),
WalletPutExport(WalletPutExport),
}
impl ClientRequestContentV0 {
pub fn set_overlay(&mut self, overlay: OverlayId) {
match self {
ClientRequestContentV0::RepoPinStatusReq(a) => a.set_overlay(overlay),
ClientRequestContentV0::TopicSub(a) => a.set_overlay(overlay),
ClientRequestContentV0::PinRepo(_a) => {}
ClientRequestContentV0::PublishEvent(a) => a.set_overlay(overlay),
ClientRequestContentV0::CommitGet(a) => a.set_overlay(overlay),
ClientRequestContentV0::TopicSyncReq(a) => a.set_overlay(overlay),
ClientRequestContentV0::BlocksPut(a) => a.set_overlay(overlay),
ClientRequestContentV0::BlocksExist(a) => a.set_overlay(overlay),
ClientRequestContentV0::BlocksGet(a) => a.set_overlay(overlay),
ClientRequestContentV0::WalletPutExport(_a) => {}
_ => unimplemented!(),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ClientRequestV0 {
pub id: i64,
pub content: ClientRequestContentV0,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ClientRequest {
V0(ClientRequestV0),
}
impl ClientRequest {
pub fn id(&self) -> i64 {
match self {
ClientRequest::V0(o) => o.id,
}
}
pub fn set_id(&mut self, id: i64) {
match self {
ClientRequest::V0(v0) => {
v0.id = id;
}
}
}
pub fn content_v0(&self) -> &ClientRequestContentV0 {
match self {
ClientRequest::V0(o) => &o.content,
}
}
pub fn get_actor(&self) -> Box<dyn EActor> {
match self {
Self::V0(ClientRequestV0 { content, .. }) => match content {
ClientRequestContentV0::RepoPinStatusReq(r) => r.get_actor(self.id()),
ClientRequestContentV0::PinRepo(r) => r.get_actor(self.id()),
ClientRequestContentV0::TopicSub(r) => r.get_actor(self.id()),
ClientRequestContentV0::PublishEvent(r) => r.get_actor(self.id()),
ClientRequestContentV0::CommitGet(r) => r.get_actor(self.id()),
ClientRequestContentV0::TopicSyncReq(r) => r.get_actor(self.id()),
ClientRequestContentV0::BlocksPut(r) => r.get_actor(self.id()),
ClientRequestContentV0::BlocksExist(r) => r.get_actor(self.id()),
ClientRequestContentV0::BlocksGet(r) => r.get_actor(self.id()),
ClientRequestContentV0::WalletPutExport(r) => r.get_actor(self.id()),
_ => unimplemented!(),
},
}
}
}
impl TryFrom<ProtocolMessage> for ClientRequestContentV0 {
type Error = ProtocolError;
fn try_from(msg: ProtocolMessage) -> Result<Self, Self::Error> {
if let ProtocolMessage::ClientMessage(ClientMessage::V0(ClientMessageV0 {
overlay,
content:
ClientMessageContentV0::ClientRequest(ClientRequest::V0(ClientRequestV0 {
mut content,
..
})),
..
})) = msg
{
content.set_overlay(overlay);
Ok(content)
} else {
log_debug!("INVALID {:?}", msg);
Err(ProtocolError::InvalidValue)
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BlocksFoundV0 {
pub found: Vec<BlockId>,
pub missing: Vec<BlockId>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum BlocksFound {
V0(BlocksFoundV0),
}
impl BlocksFound {
pub fn found(&self) -> &Vec<BlockId> {
match self {
BlocksFound::V0(o) => &o.found,
}
}
pub fn missing(&self) -> &Vec<BlockId> {
match self {
BlocksFound::V0(o) => &o.missing,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TopicSubResV0 {
pub topic: TopicId,
pub known_heads: Vec<ObjectId>,
pub publisher: bool,
pub commits_nbr: u64,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum TopicSubRes {
V0(TopicSubResV0),
}
impl TopicSubRes {
pub fn topic_id(&self) -> &TopicId {
match self {
Self::V0(v0) => &v0.topic,
}
}
pub fn is_publisher(&self) -> bool {
match self {
Self::V0(v0) => v0.publisher,
}
}
pub fn new_from_heads(
topics: HashSet<ObjectId>,
publisher: bool,
topic: TopicId,
commits_nbr: u64,
) -> Self {
TopicSubRes::V0(TopicSubResV0 {
topic,
known_heads: topics.into_iter().collect(),
publisher,
commits_nbr,
})
}
pub fn known_heads(&self) -> &Vec<ObjectId> {
match self {
Self::V0(v0) => &v0.known_heads,
}
}
pub fn commits_nbr(&self) -> u64 {
match self {
Self::V0(v0) => v0.commits_nbr,
}
}
}
impl From<TopicId> for TopicSubRes {
fn from(topic: TopicId) -> Self {
TopicSubRes::V0(TopicSubResV0 {
topic,
known_heads: vec![],
publisher: false,
commits_nbr: 0,
})
}
}
impl From<PublisherAdvert> for TopicSubRes {
fn from(topic: PublisherAdvert) -> Self {
TopicSubRes::V0(TopicSubResV0 {
topic: topic.topic_id().clone(),
known_heads: vec![],
publisher: true,
commits_nbr: 0,
})
}
}
pub type RepoOpened = Vec<TopicSubRes>;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ClientResponseContentV0 {
EmptyResponse,
Block(Block),
RepoOpened(RepoOpened),
TopicSubRes(TopicSubRes),
TopicSyncRes(TopicSyncRes),
BlocksFound(BlocksFound),
RepoPinStatus(RepoPinStatus),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ClientResponseV0 {
pub id: i64,
pub result: u16,
pub content: ClientResponseContentV0,
}
impl ClientResponse {
pub fn set_result(&mut self, res: u16) {
match self {
Self::V0(v0) => v0.result = res,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ClientResponse {
V0(ClientResponseV0),
}
impl From<ServerError> for ClientResponse {
fn from(err: ServerError) -> ClientResponse {
ClientResponse::V0(ClientResponseV0 {
id: 0,
result: err.into(),
content: ClientResponseContentV0::EmptyResponse,
})
}
}
#[derive(Debug)]
pub struct EmptyAppResponse(pub ());
impl From<ServerError> for AppMessage {
fn from(err: ServerError) -> AppMessage {
AppMessage::V0(AppMessageV0 {
id: 0,
result: err.into(),
content: AppMessageContentV0::EmptyResponse,
})
}
}
impl<A> From<Result<A, ServerError>> for ProtocolMessage
where
A: Into<ProtocolMessage> + std::fmt::Debug,
{
fn from(res: Result<A, ServerError>) -> ProtocolMessage {
match res {
Ok(a) => a.into(),
Err(e) => ProtocolMessage::from_client_response_err(e),
}
}
}
impl From<()> for ProtocolMessage {
fn from(_msg: ()) -> ProtocolMessage {
let cm: ClientResponse = ServerError::Ok.into();
cm.into()
}
}
impl ClientResponse {
pub fn id(&self) -> i64 {
match self {
ClientResponse::V0(o) => o.id,
}
}
pub fn set_id(&mut self, id: i64) {
match self {
ClientResponse::V0(v0) => {
v0.id = id;
}
}
}
pub fn result(&self) -> u16 {
match self {
ClientResponse::V0(o) => o.result,
}
}
pub fn block(&self) -> Option<&Block> {
match self {
ClientResponse::V0(o) => match &o.content {
ClientResponseContentV0::Block(b) => Some(b),
_ => panic!("this not a block response"),
},
}
}
}
impl TryFrom<ProtocolMessage> for ClientResponseContentV0 {
type Error = ProtocolError;
fn try_from(msg: ProtocolMessage) -> Result<Self, Self::Error> {
if let ProtocolMessage::ClientMessage(ClientMessage::V0(ClientMessageV0 {
content:
ClientMessageContentV0::ClientResponse(ClientResponse::V0(ClientResponseV0 {
content,
result: res,
..
})),
..
})) = msg
{
let err = ServerError::try_from(res).unwrap();
if !err.is_err() {
Ok(content)
} else {
Err(ProtocolError::ServerError)
}
} else {
log_debug!("INVALID {:?}", msg);
Err(ProtocolError::InvalidValue)
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ClientMessageContentV0 {
ClientRequest(ClientRequest),
ClientResponse(ClientResponse),
ForwardedEvent(Event),
ForwardedBlock(Block),
}
impl ClientMessageContentV0 {
pub fn is_block(&self) -> bool {
match self {
Self::ClientRequest(ClientRequest::V0(ClientRequestV0 {
content: ClientRequestContentV0::BlocksPut(_),
..
})) => true,
Self::ClientResponse(ClientResponse::V0(ClientResponseV0 {
content: ClientResponseContentV0::Block(_),
..
})) => true,
_ => false,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ClientMessageV0 {
pub overlay: OverlayId,
pub content: ClientMessageContentV0,
#[serde(with = "serde_bytes")]
pub padding: Vec<u8>,
}
pub trait IStreamable {
fn result(&self) -> u16;
fn set_result(&mut self, result: u16);
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ClientMessage {
V0(ClientMessageV0),
}
impl IStreamable for ClientMessage {
fn result(&self) -> u16 {
match self {
ClientMessage::V0(o) => match &o.content {
ClientMessageContentV0::ClientResponse(r) => r.result(),
ClientMessageContentV0::ClientRequest(_)
| ClientMessageContentV0::ForwardedEvent(_)
| ClientMessageContentV0::ForwardedBlock(_) => {
panic!("it is not a response");
}
},
}
}
fn set_result(&mut self, result: u16) {
match self {
ClientMessage::V0(o) => match &mut o.content {
ClientMessageContentV0::ClientResponse(r) => r.set_result(result),
ClientMessageContentV0::ClientRequest(_)
| ClientMessageContentV0::ForwardedEvent(_)
| ClientMessageContentV0::ForwardedBlock(_) => {
panic!("it is not a response");
}
},
}
}
}
impl ClientMessage {
pub fn content_v0(&self) -> &ClientMessageContentV0 {
match self {
ClientMessage::V0(o) => &o.content,
}
}
pub fn overlay_request(&self) -> &ClientRequest {
match self {
ClientMessage::V0(o) => match &o.content {
ClientMessageContentV0::ClientRequest(r) => &r,
_ => panic!("not an overlay request"),
},
}
}
pub fn forwarded_event(self) -> Option<(Event, OverlayId)> {
let overlay = self.overlay_id();
match self {
ClientMessage::V0(o) => match o.content {
ClientMessageContentV0::ForwardedEvent(e) => Some((e, overlay)),
_ => None,
},
}
}
pub fn overlay_id(&self) -> OverlayId {
match self {
ClientMessage::V0(o) => o.overlay,
}
}
pub fn is_request(&self) -> bool {
match self {
ClientMessage::V0(o) => {
matches!(o.content, ClientMessageContentV0::ClientRequest { .. })
}
}
}
pub fn is_response(&self) -> bool {
match self {
ClientMessage::V0(o) => {
matches!(o.content, ClientMessageContentV0::ClientResponse { .. })
}
}
}
pub fn id(&self) -> Option<i64> {
match self {
ClientMessage::V0(o) => match &o.content {
ClientMessageContentV0::ClientResponse(r) => Some(r.id()),
ClientMessageContentV0::ClientRequest(r) => Some(r.id()),
ClientMessageContentV0::ForwardedEvent(_)
| ClientMessageContentV0::ForwardedBlock(_) => None,
},
}
}
pub fn set_id(&mut self, id: i64) {
match self {
ClientMessage::V0(o) => match &mut o.content {
ClientMessageContentV0::ClientResponse(ref mut r) => r.set_id(id),
ClientMessageContentV0::ClientRequest(ref mut r) => r.set_id(id),
ClientMessageContentV0::ForwardedEvent(_)
| ClientMessageContentV0::ForwardedBlock(_) => {
panic!("it is an event")
}
},
}
}
pub fn block<'a>(&self) -> Option<&Block> {
match self {
ClientMessage::V0(o) => match &o.content {
ClientMessageContentV0::ClientResponse(r) => r.block(),
ClientMessageContentV0::ClientRequest(_)
| ClientMessageContentV0::ForwardedEvent(_)
| ClientMessageContentV0::ForwardedBlock(_) => {
panic!("it is not a response");
}
},
}
}
pub fn get_actor(&self) -> Box<dyn EActor> {
match self {
ClientMessage::V0(o) => match &o.content {
ClientMessageContentV0::ClientRequest(req) => req.get_actor(),
ClientMessageContentV0::ClientResponse(_)
| ClientMessageContentV0::ForwardedEvent(_)
| ClientMessageContentV0::ForwardedBlock(_) => {
panic!("it is not a request");
}
},
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ExtObjectGetV0 {
pub overlay: OverlayId,
pub ids: Vec<ObjectId>,
pub include_files: bool,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ExtObjectGet {
V0(ExtObjectGetV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ExtWalletGetExportV0 {
pub id: SymKey,
pub is_rendezvous: bool,
}
pub type ExtTopicSyncReq = TopicSyncReq;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ExtRequestContentV0 {
WalletGetExport(ExtWalletGetExportV0),
ExtObjectGet(ExtObjectGetV0),
ExtTopicSyncReq(ExtTopicSyncReq),
}
impl ExtRequestContentV0 {
pub fn get_actor(&self) -> Box<dyn EActor> {
match self {
Self::WalletGetExport(a) => a.get_actor(),
Self::ExtObjectGet(a) => a.get_actor(),
_ => unimplemented!(), }
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ExtRequestV0 {
pub id: i64,
pub content: ExtRequestContentV0,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ExtRequest {
V0(ExtRequestV0),
}
impl ExtRequest {
pub fn id(&self) -> i64 {
match self {
ExtRequest::V0(v0) => v0.id,
}
}
pub fn set_id(&mut self, id: i64) {
match self {
ExtRequest::V0(v0) => {
v0.id = id;
}
}
}
pub fn get_actor(&self) -> Box<dyn EActor> {
match self {
Self::V0(a) => a.content.get_actor(),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ExportedWallet(pub serde_bytes::ByteBuf);
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ExtResponseContentV0 {
EmptyResponse,
Block(Block),
Blocks(Vec<Block>),
Wallet(ExportedWallet),
}
impl TryFrom<ProtocolMessage> for ExtResponseContentV0 {
type Error = ProtocolError;
fn try_from(msg: ProtocolMessage) -> Result<Self, Self::Error> {
if let ProtocolMessage::ExtResponse(ExtResponse::V0(ExtResponseV0 {
content,
result,
..
})) = msg
{
let err = ServerError::try_from(result).unwrap();
if !err.is_err() {
Ok(content)
} else {
Err(ProtocolError::ServerError)
}
} else {
log_debug!("INVALID {:?}", msg);
Err(ProtocolError::InvalidValue)
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ExtResponseV0 {
pub id: i64,
pub result: u16,
pub content: ExtResponseContentV0,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ExtResponse {
V0(ExtResponseV0),
}
impl ExtResponse {
pub fn id(&self) -> i64 {
match self {
ExtResponse::V0(v0) => v0.id,
}
}
pub fn set_id(&mut self, id: i64) {
match self {
ExtResponse::V0(v0) => {
v0.id = id;
}
}
}
pub fn result(&self) -> u16 {
match self {
Self::V0(o) => o.result,
}
}
pub fn content_v0(&self) -> ExtResponseContentV0 {
match self {
Self::V0(o) => o.content.clone(),
}
}
}
impl TryFrom<ProtocolMessage> for ExtResponse {
type Error = ProtocolError;
fn try_from(msg: ProtocolMessage) -> Result<Self, Self::Error> {
if let ProtocolMessage::ExtResponse(ext_res) = msg {
Ok(ext_res)
} else {
Err(ProtocolError::InvalidValue)
}
}
}
impl From<Result<ExtResponseContentV0, ServerError>> for ExtResponseV0 {
fn from(res: Result<ExtResponseContentV0, ServerError>) -> ExtResponseV0 {
match res {
Err(e) => ExtResponseV0 {
id: 0,
result: e.into(),
content: ExtResponseContentV0::EmptyResponse,
},
Ok(content) => ExtResponseV0 {
id: 0,
result: 0,
content,
},
}
}
}
impl From<ExtResponseV0> for ProtocolMessage {
fn from(msg: ExtResponseV0) -> ProtocolMessage {
ProtocolMessage::ExtResponse(ExtResponse::V0(msg))
}
}
#[doc(hidden)]
pub static MAGIC_NG_REQUEST: [u8; 2] = [78u8, 71u8];
#[doc(hidden)]
pub static MAGIC_NG_RESPONSE: [u8; 4] = [89u8, 88u8, 78u8, 75u8];
#[derive(Clone, Debug)]
pub enum Authorization {
Discover,
ExtMessage,
Core,
Client((PubKey, Option<Option<[u8; 32]>>)),
OverlayJoin(PubKey),
Admin(PubKey),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ProbeResponse {
#[serde(with = "serde_bytes")]
pub magic: Vec<u8>,
pub peer_id: Option<PubKey>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RelayRequest {
pub address: BindAddress,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RelayResponse {
#[serde(with = "serde_bytes")]
pub magic: Vec<u8>,
pub result: u16,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TunnelRequest {
#[serde(with = "serde_bytes")]
pub magic: Vec<u8>,
pub remote_addr: BindAddress,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TunnelResponse {
#[serde(with = "serde_bytes")]
pub magic: Vec<u8>,
pub result: u16,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ProtocolMessage {
Probe([u8; 2]),
ProbeResponse(ProbeResponse),
Relay(RelayRequest),
RelayResponse(RelayResponse),
Tunnel(TunnelRequest),
TunnelResponse(TunnelResponse),
Noise(Noise),
Start(StartProtocol),
ServerHello(ServerHello),
ClientAuth(ClientAuth),
AuthResult(AuthResult),
ExtRequest(ExtRequest),
ExtResponse(ExtResponse),
AdminResponse(AdminResponse),
ClientMessage(ClientMessage),
AppMessage(AppMessage),
CoreMessage(CoreMessage),
}
impl TryFrom<&ProtocolMessage> for ServerError {
type Error = NgError;
fn try_from(msg: &ProtocolMessage) -> Result<Self, NgError> {
if let ProtocolMessage::ClientMessage(ref bm) = msg {
let res = bm.result();
if res != 0 {
return Ok(ServerError::try_from(res).unwrap());
}
}
if let ProtocolMessage::ExtResponse(ref bm) = msg {
let res = bm.result();
if res != 0 {
return Ok(ServerError::try_from(res).unwrap());
}
}
if let ProtocolMessage::AppMessage(ref bm) = msg {
let res = bm.result();
if res != 0 {
return Ok(ServerError::try_from(res).unwrap());
}
}
Err(NgError::NotAServerError)
}
}
impl ProtocolMessage {
pub fn id(&self) -> Option<i64> {
match self {
ProtocolMessage::ExtRequest(ext_req) => Some(ext_req.id()),
ProtocolMessage::ExtResponse(ext_res) => Some(ext_res.id()),
ProtocolMessage::ClientMessage(client_msg) => client_msg.id(),
ProtocolMessage::AppMessage(app_msg) => app_msg.id(),
_ => None,
}
}
pub fn set_id(&mut self, id: i64) {
match self {
ProtocolMessage::ExtRequest(ext_req) => ext_req.set_id(id),
ProtocolMessage::ExtResponse(ext_res) => ext_res.set_id(id),
ProtocolMessage::ClientMessage(client_msg) => client_msg.set_id(id),
ProtocolMessage::AppMessage(app_msg) => app_msg.set_id(id),
_ => panic!("cannot set ID"),
}
}
pub fn type_id(&self) -> TypeId {
match self {
ProtocolMessage::Noise(a) => a.type_id(),
ProtocolMessage::Start(a) => a.type_id(),
ProtocolMessage::ServerHello(a) => a.type_id(),
ProtocolMessage::ClientAuth(a) => a.type_id(),
ProtocolMessage::AuthResult(a) => a.type_id(),
ProtocolMessage::ExtRequest(a) => a.type_id(),
ProtocolMessage::ExtResponse(a) => a.type_id(),
ProtocolMessage::ClientMessage(a) => a.type_id(),
ProtocolMessage::CoreMessage(a) => a.type_id(),
ProtocolMessage::AppMessage(a) => a.type_id(),
ProtocolMessage::AdminResponse(a) => a.type_id(),
ProtocolMessage::Probe(a) => a.type_id(),
ProtocolMessage::ProbeResponse(a) => a.type_id(),
ProtocolMessage::Relay(a) => a.type_id(),
ProtocolMessage::RelayResponse(a) => a.type_id(),
ProtocolMessage::Tunnel(a) => a.type_id(),
ProtocolMessage::TunnelResponse(a) => a.type_id(),
}
}
pub(crate) fn is_streamable(&self) -> Option<&dyn IStreamable> {
match self {
ProtocolMessage::ClientMessage(s) => Some(s as &dyn IStreamable),
ProtocolMessage::AppMessage(s) => Some(s as &dyn IStreamable),
_ => None,
}
}
pub fn get_actor(&self) -> Box<dyn EActor> {
match self {
ProtocolMessage::Start(a) => a.get_actor(),
ProtocolMessage::ClientMessage(a) => a.get_actor(),
ProtocolMessage::AppMessage(a) => a.get_actor(),
_ => unimplemented!(),
}
}
pub fn from_client_response_err(err: ServerError) -> ProtocolMessage {
let res: ClientResponse = err.into();
res.into()
}
pub fn from_client_request_v0(
req: ClientRequestContentV0,
overlay: OverlayId,
) -> ProtocolMessage {
ProtocolMessage::ClientMessage(ClientMessage::V0(ClientMessageV0 {
overlay,
content: ClientMessageContentV0::ClientRequest(ClientRequest::V0(ClientRequestV0 {
id: 0,
content: req,
})),
padding: vec![],
}))
}
pub fn is_block(&self) -> bool {
match self {
ProtocolMessage::ClientMessage(ClientMessage::V0(ClientMessageV0 {
content: c,
..
})) => c.is_block(),
_ => false,
}
}
}
impl From<ClientResponseContentV0> for ClientResponse {
fn from(msg: ClientResponseContentV0) -> ClientResponse {
ClientResponse::V0(ClientResponseV0 {
id: 0,
result: 0,
content: msg,
})
}
}
impl From<ClientResponseContentV0> for ProtocolMessage {
fn from(msg: ClientResponseContentV0) -> ProtocolMessage {
let client_res = ClientResponse::V0(ClientResponseV0 {
id: 0,
result: 0,
content: msg,
});
client_res.into()
}
}
impl From<ClientResponse> for ProtocolMessage {
fn from(msg: ClientResponse) -> ProtocolMessage {
ProtocolMessage::ClientMessage(ClientMessage::V0(ClientMessageV0 {
overlay: OverlayId::nil(),
content: ClientMessageContentV0::ClientResponse(msg),
padding: vec![],
}))
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ClientAuthContentV0 {
pub user: PubKey,
pub client: PubKey,
pub info: ClientInfoV0,
pub registration: Option<Option<[u8; 32]>>,
#[serde(with = "serde_bytes")]
pub nonce: Vec<u8>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ClientAuthV0 {
pub content: ClientAuthContentV0,
pub sig: Sig,
pub client_sig: Sig,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ClientAuth {
V0(ClientAuthV0),
}
impl ClientAuth {
pub fn content_v0(&self) -> ClientAuthContentV0 {
match self {
ClientAuth::V0(o) => o.content.clone(),
}
}
pub fn sig(&self) -> Sig {
match self {
ClientAuth::V0(o) => o.sig,
}
}
pub fn user(&self) -> PubKey {
match self {
ClientAuth::V0(o) => o.content.user,
}
}
pub fn client(&self) -> PubKey {
match self {
ClientAuth::V0(o) => o.content.client,
}
}
pub fn nonce(&self) -> &Vec<u8> {
match self {
ClientAuth::V0(o) => &o.content.nonce,
}
}
pub fn registration(&self) -> Option<Option<[u8; 32]>> {
match self {
ClientAuth::V0(o) => o.content.registration,
}
}
}
impl From<ClientAuth> for ProtocolMessage {
fn from(msg: ClientAuth) -> ProtocolMessage {
ProtocolMessage::ClientAuth(msg)
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AuthResultV0 {
pub result: u16,
#[serde(with = "serde_bytes")]
pub metadata: Vec<u8>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AuthResult {
V0(AuthResultV0),
}
impl AuthResult {
pub fn result(&self) -> u16 {
match self {
AuthResult::V0(o) => o.result,
}
}
pub fn metadata(&self) -> &Vec<u8> {
match self {
AuthResult::V0(o) => &o.metadata,
}
}
}
impl From<AuthResult> for ProtocolMessage {
fn from(msg: AuthResult) -> ProtocolMessage {
ProtocolMessage::AuthResult(msg)
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RepoLinkV0 {
pub id: RepoId,
pub read_cap: ReadCap,
pub overlay: OverlayLink,
pub peers: Vec<PeerAdvert>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum RepoLink {
V0(RepoLinkV0),
}
impl RepoLink {
pub fn id(&self) -> &RepoId {
match self {
RepoLink::V0(o) => &o.id,
}
}
pub fn peers(&self) -> &Vec<PeerAdvert> {
match self {
RepoLink::V0(o) => &o.peers,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PublicRepoLinkV0 {
pub repo: RepoId,
pub branch: Option<BranchId>,
pub heads: Vec<ObjectRef>,
pub snapshot: Option<ObjectRef>,
pub public_store: PubKey,
pub peers: Vec<PeerAdvert>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum PublicRepoLink {
V0(PublicRepoLinkV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ReadBranchLinkV0 {
pub repo: RepoId,
pub branch: BranchId,
pub topic: TopicId,
pub heads: Vec<ObjectRef>,
pub read_cap: ReadCap,
pub overlay: OverlayLink,
pub peers: Vec<PeerAdvert>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ReadBranchLink {
V0(ReadBranchLinkV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ObjectLinkV0 {
pub repo: Option<RepoId>,
pub topic: Option<TopicId>,
pub objects: Vec<ObjectRef>,
pub overlay: OverlayLink,
pub peers: Vec<PeerAdvert>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ObjectLink {
V0(ObjectLinkV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NgLinkV0 {
Repo(RepoLink),
PublicRepo(PublicRepoLink),
Branch(ReadBranchLink),
Object(ObjectLink),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NgLink {
V0(NgLinkV0),
}
#[cfg(test)]
mod test {
use crate::types::{BootstrapContentV0, BrokerServerTypeV0, BrokerServerV0, Invitation};
use ng_repo::types::PubKey;
#[test]
pub fn invitation() {
let inv = Invitation::new_v0(
BootstrapContentV0 {
servers: vec![BrokerServerV0 {
server_type: BrokerServerTypeV0::Localhost(14400),
can_verify: false,
can_forward: false,
peer_id: PubKey::Ed25519PubKey([
95, 73, 225, 250, 3, 147, 24, 164, 177, 211, 34, 244, 45, 130, 111, 136,
229, 145, 53, 167, 50, 168, 140, 227, 65, 111, 203, 41, 210, 186, 162, 149,
]),
}],
},
Some("test invitation".to_string()),
None,
);
println!("{:?}", inv.get_urls());
}
}