serving app and .ng_bootstrap

pull/19/head
Niko PLP 2 years ago
parent cd1f9822a0
commit a27816ddb6
  1. 528
      Cargo.lock
  2. 11
      README.md
  3. 3
      ng-app/package.json
  4. 30
      ng-app/prepare-app-file.cjs
  5. 8
      ng-app/src/routes/WalletCreate.svelte
  6. 9
      ng-wallet/src/types.rs
  7. 5
      ngd/src/main.rs
  8. 11
      ngone/README.md
  9. 4
      p2p-broker/Cargo.toml
  10. 180
      p2p-broker/src/server_ws.rs
  11. 2
      p2p-client-ws/Cargo.toml
  12. 67
      p2p-net/src/types.rs
  13. 73
      pnpm-lock.yaml

528
Cargo.lock generated

File diff suppressed because it is too large Load Diff

@ -108,6 +108,17 @@ cargo test --package p2p-client-ws --lib -- --nocapture
### Build release binaries ### Build release binaries
First you will need to build the single-file release of ng-app.
```
// uncomment line 14 of src/App.svelte: import * as api from "ng-sdk-js";
cd ng-app
pnpm filebuild
cd ..
```
then build the ngd daemon
``` ```
cargo build -r -p ngd cargo build -r -p ngd
``` ```

@ -7,7 +7,7 @@
"dev": "vite", "dev": "vite",
"webdev": "cross-env NG_APP_WEB=1 TAURI_DEBUG=1 vite", "webdev": "cross-env NG_APP_WEB=1 TAURI_DEBUG=1 vite",
"webbuild": "cross-env NG_APP_WEB=1 vite build", "webbuild": "cross-env NG_APP_WEB=1 vite build",
"filebuild": "cross-env NG_APP_WEB=1 NG_APP_FILE=1 vite build", "filebuild": "cross-env NG_APP_WEB=1 NG_APP_FILE=1 vite build && node prepare-app-file.cjs",
"filebuilddebug": "cross-env NG_APP_WEB=1 NG_APP_FILE=1 TAURI_DEBUG=1 vite build -m debug", "filebuilddebug": "cross-env NG_APP_WEB=1 NG_APP_FILE=1 TAURI_DEBUG=1 vite build -m debug",
"build": "vite build", "build": "vite build",
"preview": "vite preview", "preview": "vite preview",
@ -33,6 +33,7 @@
"autoprefixer": "^10.4.14", "autoprefixer": "^10.4.14",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"internal-ip": "^7.0.0", "internal-ip": "^7.0.0",
"node-gzip": "^1.1.2",
"postcss": "^8.4.23", "postcss": "^8.4.23",
"postcss-load-config": "^4.0.1", "postcss-load-config": "^4.0.1",
"svelte": "^3.54.0", "svelte": "^3.54.0",

@ -0,0 +1,30 @@
var crypto = require('crypto')
, fs = require('fs')
const {gzip, } = require('node-gzip');
var algorithm = 'sha256'
, shasum = crypto.createHash(algorithm)
const sha_file = './dist-file/index.sha256';
const gzip_file = './dist-file/index.gzip';
var filename = './dist-file/index.html'
, s = fs.ReadStream(filename)
var bufs = [];
s.on('data', function(data) {
shasum.update(data)
bufs.push(data);
})
s.on('end', function() {
var hash = shasum.digest('hex')
console.log(hash + ' ' + filename)
fs.writeFileSync(sha_file, hash, 'utf8');
var buf = Buffer.concat(bufs);
gzip(buf).then((compressed) => {fs.writeFileSync(gzip_file, compressed);});
})

@ -557,10 +557,10 @@
This security measure will prevent you from entering your pazzle and PIN This security measure will prevent you from entering your pazzle and PIN
on malicious sites and apps. on malicious sites and apps.
<Alert color="red" class="mt-5"> <Alert color="red" class="mt-5">
When you will use you wallet, if you do not see and recognize your Every time you will use your wallet, if you do not see and recognize
own security phrase and image before entering your pazzle, please your own security phrase and image before entering your pazzle,
stop and DO NOT enter your pazzle, you are being the victim of a please stop and DO NOT enter your pazzle, as you would be the victim
phishing attempt. of a phishing attempt.
</Alert> </Alert>
</p> </p>
<p class="text-left mt-5"> <p class="text-left mt-5">

@ -12,7 +12,7 @@ use std::fmt;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_big_array::BigArray; use serde_big_array::BigArray;
use p2p_net::types::{BrokerServerV0, NetAddr}; use p2p_net::types::{BootstrapContentV0, BrokerServerV0};
use p2p_repo::types::*; use p2p_repo::types::*;
/// WalletId is a PubKey /// WalletId is a PubKey
@ -21,13 +21,6 @@ pub type WalletId = PubKey;
/// BootstrapId is a WalletId /// BootstrapId is a WalletId
pub type BootstrapId = WalletId; pub type BootstrapId = WalletId;
/// Bootstrap content Version 0
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BootstrapContentV0 {
/// list of servers, in order of preference
pub servers: Vec<BrokerServerV0>,
}
/// Bootstrap Version 0 /// Bootstrap Version 0
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BootstrapV0 { pub struct BootstrapV0 {

@ -577,6 +577,7 @@ async fn main_inner() -> Result<(), ()> {
} else { } else {
listener.refuse_clients = true; listener.refuse_clients = true;
} }
listener.serve_app = false;
listeners.push(listener); listeners.push(listener);
} }
} }
@ -645,7 +646,7 @@ async fn main_inner() -> Result<(), ()> {
port: private_part.1, port: private_part.1,
discoverable: false, discoverable: false,
refuse_clients: args.public_without_clients, refuse_clients: args.public_without_clients,
serve_app: true, serve_app: false,
accept_direct: false, accept_direct: false,
accept_forward_for: AcceptForwardForV0::PublicStatic(( accept_forward_for: AcceptForwardForV0::PublicStatic((
BindAddress { BindAddress {
@ -720,6 +721,7 @@ async fn main_inner() -> Result<(), ()> {
let mut listener = let mut listener =
ListenerV0::new_direct(inter, !args.no_ipv6, arg_value.1); ListenerV0::new_direct(inter, !args.no_ipv6, arg_value.1);
listener.accept_direct = false; listener.accept_direct = false;
listener.serve_app = false;
listener.accept_forward_for = listener.accept_forward_for =
AcceptForwardForV0::PublicDyn((public_port, 60, "".to_string())); AcceptForwardForV0::PublicDyn((public_port, 60, "".to_string()));
listeners.push(listener); listeners.push(listener);
@ -829,6 +831,7 @@ async fn main_inner() -> Result<(), ()> {
{ {
let r = listeners.last_mut().unwrap(); let r = listeners.last_mut().unwrap();
r.accept_direct = true; r.accept_direct = true;
r.serve_app = true;
r.ipv6 = !args.no_ipv6; r.ipv6 = !args.no_ipv6;
} else { } else {
listeners.push(ListenerV0::new_direct(inter, !args.no_ipv6, arg_value.1)); listeners.push(ListenerV0::new_direct(inter, !args.no_ipv6, arg_value.1));

@ -23,6 +23,17 @@ cargo watch -c -w src -x run
## Build ## Build
First you will need to build the single-file release of ng-app.
```
// uncomment line 14 of src/App.svelte: import * as api from "ng-sdk-js";
cd ../ng-app
pnpm filebuild
cd ../ngone
```
then, in ngone:
``` ```
cd web cd web
pnpm run build pnpm run build

@ -22,9 +22,11 @@ async-channel = "1.7.1"
tempfile = "3" tempfile = "3"
hex = "0.4.3" hex = "0.4.3"
async-trait = "0.1.64" async-trait = "0.1.64"
async-tungstenite = { version = "0.22.2", features = ["async-std-runtime"] } async-tungstenite = { git = "https://git.nextgraph.org/NextGraph/async-tungstenite.git", branch = "nextgraph", features = ["async-std-runtime"] }
blake3 = "1.3.1" blake3 = "1.3.1"
once_cell = "1.17.1" once_cell = "1.17.1"
rust-embed= { version = "6.7.0", features=["include-exclude"] }
serde_json = "1.0.96"
[target.'cfg(target_arch = "wasm32")'.dependencies.getrandom] [target.'cfg(target_arch = "wasm32")'.dependencies.getrandom]
version = "0.2.7" version = "0.2.7"

@ -21,11 +21,15 @@ use async_tungstenite::accept_hdr_async;
use async_tungstenite::tungstenite::handshake::server::{ use async_tungstenite::tungstenite::handshake::server::{
Callback, ErrorResponse, Request, Response, Callback, ErrorResponse, Request, Response,
}; };
use async_tungstenite::tungstenite::http::header::{CONNECTION, HOST, ORIGIN, UPGRADE};
use async_tungstenite::tungstenite::http::HeaderValue; use async_tungstenite::tungstenite::http::{
use async_tungstenite::tungstenite::http::StatusCode; header::{CONNECTION, HOST, ORIGIN, UPGRADE},
HeaderValue, Method, StatusCode, Uri, Version,
};
use async_tungstenite::tungstenite::protocol::Message; use async_tungstenite::tungstenite::protocol::Message;
use futures::{SinkExt, StreamExt}; use futures::{SinkExt, StreamExt};
use once_cell::sync::Lazy;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use p2p_client_ws::remote_ws::ConnectionWebSocket; use p2p_client_ws::remote_ws::ConnectionWebSocket;
use p2p_net::broker::*; use p2p_net::broker::*;
@ -37,11 +41,14 @@ use p2p_net::utils::{get_domain_without_port, Sensitive, U8Array};
use p2p_repo::log::*; use p2p_repo::log::*;
use p2p_repo::types::{PrivKey, PubKey}; use p2p_repo::types::{PrivKey, PubKey};
use p2p_repo::utils::generate_keypair; use p2p_repo::utils::generate_keypair;
use rust_embed::RustEmbed;
use serde_json::json;
use std::collections::HashMap; use std::collections::HashMap;
use std::collections::HashSet; use std::collections::HashSet;
use std::fs; use std::fs;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::num::NonZeroU8;
use std::ops::Deref; use std::ops::Deref;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::Arc; use std::sync::Arc;
@ -52,6 +59,9 @@ use tempfile::Builder;
static LISTENERS_INFO: OnceCell<(HashMap<String, ListenerInfo>, HashMap<BindAddress, String>)> = static LISTENERS_INFO: OnceCell<(HashMap<String, ListenerInfo>, HashMap<BindAddress, String>)> =
OnceCell::new(); OnceCell::new();
static BOOTSTRAP_STRING: OnceCell<String> = OnceCell::new();
struct SecurityCallback { struct SecurityCallback {
remote_bind_address: BindAddress, remote_bind_address: BindAddress,
local_bind_address: BindAddress, local_bind_address: BindAddress,
@ -178,25 +188,69 @@ fn prepare_urls_from_private_addrs(addrs: &Vec<BindAddress>, port: u16) -> Vec<S
res res
} }
#[derive(RustEmbed)]
#[folder = "../ng-app/dist-file/"]
#[include = "*.sha256"]
#[include = "*.gzip"]
struct App;
fn upgrade_ws_or_serve_app( fn upgrade_ws_or_serve_app(
upgrade: Option<&HeaderValue>, connection: Option<&HeaderValue>,
remote: IP, remote: IP,
serve_app: bool, serve_app: bool,
response: Response, uri: &Uri,
) -> Result<Response, ErrorResponse> { last_etag: Option<&HeaderValue>,
if upgrade.is_some() ) -> Result<(), ErrorResponse> {
&& upgrade if connection.is_some()
&& connection
.unwrap() .unwrap()
.to_str() .to_str()
.unwrap() .unwrap()
.split(|c| c == ' ' || c == ',') .split(|c| c == ' ' || c == ',')
.any(|p| p.eq_ignore_ascii_case("Upgrade")) .any(|p| p.eq_ignore_ascii_case("Upgrade"))
{ {
return Ok(response); return Ok(());
} }
if serve_app && (remote.is_private() || remote.is_loopback()) { if serve_app && (remote.is_private() || remote.is_loopback()) {
return Err(make_error(StatusCode::OK)); if uri == "/" {
log_debug!("Serving the app");
let sha_file = App::get("index.sha256").unwrap();
let sha = format!(
"\"{}\"",
std::str::from_utf8(sha_file.data.as_ref()).unwrap()
);
if last_etag.is_some() && last_etag.unwrap().to_str().unwrap() == sha {
// return 304
let res = Response::builder()
.status(StatusCode::NOT_MODIFIED)
.header("Cache-Control", "max-age=31536000, must-revalidate")
.header("ETag", sha)
.body(None)
.unwrap();
return Err(res);
}
let file = App::get("index.gzip").unwrap();
let res = Response::builder()
.status(StatusCode::OK)
.header("Content-Type", "text/html")
.header("Cache-Control", "max-age=31536000, must-revalidate")
.header("Content-Encoding", "gzip")
.header("ETag", sha)
.body(Some(file.data.to_vec()))
.unwrap();
return Err(res);
} else if uri == "/.ng_bootstrap" {
log_debug!("Serving bootstrap");
let res = Response::builder()
.status(StatusCode::OK)
.header("Content-Type", "text/json")
.header("Cache-Control", "max-age=3600, must-revalidate")
.body(Some(BOOTSTRAP_STRING.get().unwrap().as_bytes().to_vec()))
.unwrap();
return Err(res);
}
} }
Err(make_error(StatusCode::FORBIDDEN)) Err(make_error(StatusCode::FORBIDDEN))
@ -207,7 +261,7 @@ const LOCAL_URLS: [&str; 3] = ["http://localhost", "http://127.0.0.1", "http://:
const APP_NG_ONE_URL: &str = "https://app.nextgraph.one"; const APP_NG_ONE_URL: &str = "https://app.nextgraph.one";
impl Callback for SecurityCallback { impl Callback for SecurityCallback {
fn on_request(self, request: &Request, response: Response) -> Result<Response, ErrorResponse> { fn on_request(self, request: &Request) -> Result<(), ErrorResponse> {
let local_urls = LOCAL_URLS let local_urls = LOCAL_URLS
.to_vec() .to_vec()
.iter() .iter()
@ -236,21 +290,30 @@ impl Callback for SecurityCallback {
.get(listener_id) .get(listener_id)
.ok_or(make_error(StatusCode::FORBIDDEN))?; .ok_or(make_error(StatusCode::FORBIDDEN))?;
if request.method() != Method::GET {
return Err(make_error(StatusCode::METHOD_NOT_ALLOWED));
}
if request.version() != Version::HTTP_11 {
return Err(make_error(StatusCode::HTTP_VERSION_NOT_SUPPORTED));
}
let xff = request.headers().get("X-Forwarded-For"); let xff = request.headers().get("X-Forwarded-For");
let upgrade = request.headers().get(CONNECTION); let connection = request.headers().get(CONNECTION);
let host = request.headers().get(HOST); let host = request.headers().get(HOST);
let origin = request.headers().get(ORIGIN); let origin = request.headers().get(ORIGIN);
let remote = self.remote_bind_address.ip; let remote = self.remote_bind_address.ip;
let xff = request.headers().get("X-Forwarded-For"); let last_etag = request.headers().get("If-None-Match");
let uri = request.uri();
log_debug!( log_debug!(
"upgrade:{:?} origin:{:?} host:{:?} xff:{:?} remote:{:?} local:{:?}", "connection:{:?} origin:{:?} host:{:?} xff:{:?} remote:{:?} local:{:?} uri:{:?}",
upgrade, connection,
origin, origin,
host, host,
xff, xff,
remote, remote,
self.local_bind_address self.local_bind_address,
uri
); );
match listener.config.if_type { match listener.config.if_type {
@ -270,7 +333,13 @@ impl Callback for SecurityCallback {
"accepted core with refuse_clients {}", "accepted core with refuse_clients {}",
listener.config.refuse_clients listener.config.refuse_clients
); );
return Ok(response); return upgrade_ws_or_serve_app(
connection,
remote,
listener.config.serve_app,
uri,
last_etag,
);
} }
InterfaceType::Loopback => { InterfaceType::Loopback => {
if !remote.is_loopback() { if !remote.is_loopback() {
@ -293,10 +362,11 @@ impl Callback for SecurityCallback {
listener.config.accept_direct listener.config.accept_direct
); );
return upgrade_ws_or_serve_app( return upgrade_ws_or_serve_app(
upgrade, connection,
remote, remote,
listener.config.serve_app, listener.config.serve_app,
response, uri,
last_etag,
); );
} else if listener.config.accept_forward_for.is_private_domain() { } else if listener.config.accept_forward_for.is_private_domain() {
let (hosts_str, urls_str) = let (hosts_str, urls_str) =
@ -305,14 +375,26 @@ impl Callback for SecurityCallback {
check_host(host, hosts_str)?; check_host(host, hosts_str)?;
check_xff_is_public_or_private(xff, false, false)?; check_xff_is_public_or_private(xff, false, false)?;
log_debug!("accepted loopback PRIVATE_DOMAIN"); log_debug!("accepted loopback PRIVATE_DOMAIN");
return Ok(response); return upgrade_ws_or_serve_app(
connection,
remote,
listener.config.serve_app,
uri,
last_etag,
);
} else if listener.config.accept_forward_for == AcceptForwardForV0::No { } else if listener.config.accept_forward_for == AcceptForwardForV0::No {
check_host(host, local_hosts)?; check_host(host, local_hosts)?;
check_no_xff(xff)?; check_no_xff(xff)?;
// TODO local_urls might need a trailing :port, but it is ok for now as we do starts_with // TODO local_urls might need a trailing :port, but it is ok for now as we do starts_with
check_origin_is_url(origin, local_urls)?; check_origin_is_url(origin, local_urls)?;
log_debug!("accepted loopback DIRECT"); log_debug!("accepted loopback DIRECT");
return Ok(response); return upgrade_ws_or_serve_app(
connection,
remote,
listener.config.serve_app,
uri,
last_etag,
);
} }
} }
InterfaceType::Private => { InterfaceType::Private => {
@ -347,7 +429,13 @@ impl Callback for SecurityCallback {
check_origin_is_url(origin, urls_str)?; check_origin_is_url(origin, urls_str)?;
check_host_in_addrs(host, &addrs)?; check_host_in_addrs(host, &addrs)?;
log_debug!("accepted private PUBLIC_STATIC or PUBLIC_DYN with direct {} with refuse_clients {}",listener.config.accept_direct, listener.config.refuse_clients); log_debug!("accepted private PUBLIC_STATIC or PUBLIC_DYN with direct {} with refuse_clients {}",listener.config.accept_direct, listener.config.refuse_clients);
return Ok(response); return upgrade_ws_or_serve_app(
connection,
remote,
listener.config.serve_app,
uri,
last_etag,
);
} else if listener.config.accept_forward_for.is_public_domain() { } else if listener.config.accept_forward_for.is_public_domain() {
if !remote.is_private() { if !remote.is_private() {
return Err(make_error(StatusCode::FORBIDDEN)); return Err(make_error(StatusCode::FORBIDDEN));
@ -373,7 +461,13 @@ impl Callback for SecurityCallback {
"accepted private PUBLIC_DOMAIN with direct {}", "accepted private PUBLIC_DOMAIN with direct {}",
listener.config.accept_direct listener.config.accept_direct
); );
return Ok(response); return upgrade_ws_or_serve_app(
connection,
remote,
listener.config.serve_app,
uri,
last_etag,
);
} else if listener.config.accept_forward_for == AcceptForwardForV0::No { } else if listener.config.accept_forward_for == AcceptForwardForV0::No {
if !remote.is_private() { if !remote.is_private() {
return Err(make_error(StatusCode::FORBIDDEN)); return Err(make_error(StatusCode::FORBIDDEN));
@ -387,7 +481,13 @@ impl Callback for SecurityCallback {
prepare_urls_from_private_addrs(&listener.addrs, listener.config.port), prepare_urls_from_private_addrs(&listener.addrs, listener.config.port),
)?; )?;
log_debug!("accepted private DIRECT"); log_debug!("accepted private DIRECT");
return Ok(response); return upgrade_ws_or_serve_app(
connection,
remote,
listener.config.serve_app,
uri,
last_etag,
);
} }
} }
_ => {} _ => {}
@ -410,10 +510,7 @@ pub async fn accept(tcp: TcpStream, peer_priv_key: Sensitive<[u8; 32]>) {
) )
.await; .await;
if ws.is_err() { if ws.is_err() {
log_debug!("websocket rejected {:?}", ws.err()); log_debug!("websocket rejected");
//let mut buffer = Vec::new();
//tcp.read_to_end(&mut buffer).await;
//log_debug!("{:?}", buffer);
return; return;
} }
@ -459,7 +556,7 @@ pub async fn run_server_accept_one(
pub async fn run_server_v0( pub async fn run_server_v0(
peer_priv_key: Sensitive<[u8; 32]>, peer_priv_key: Sensitive<[u8; 32]>,
peer_pub_key: PubKey, peer_id: PubKey,
wallet_master_key: Sensitive<[u8; 32]>, wallet_master_key: Sensitive<[u8; 32]>,
config: DaemonConfigV0, config: DaemonConfigV0,
mut path: PathBuf, mut path: PathBuf,
@ -512,9 +609,12 @@ pub async fn run_server_v0(
let mut listeners_addrs: Vec<(Vec<SocketAddr>, String)> = vec![]; let mut listeners_addrs: Vec<(Vec<SocketAddr>, String)> = vec![];
let mut listeners: Vec<TcpListener> = vec![]; let mut listeners: Vec<TcpListener> = vec![];
let mut accept_clients = false; let mut accept_clients = false;
//let mut serve_app = false;
// TODO: check that there is only one PublicDyn or one PublicStatic or one Core // TODO: check that there is only one PublicDyn or one PublicStatic or one Core
let mut servers: Vec<BrokerServerV0> = vec![];
// Preparing the listeners addrs and infos // Preparing the listeners addrs and infos
for listener in config.listeners { for listener in config.listeners {
if !listener.accept_direct && listener.accept_forward_for == AcceptForwardForV0::No { if !listener.accept_direct && listener.accept_forward_for == AcceptForwardForV0::No {
@ -576,11 +676,26 @@ pub async fn run_server_v0(
listener.interface_name listener.interface_name
); );
} }
// if listener.serve_app {
// serve_app = true;
// }
let bind_addresses: Vec<BindAddress> =
addrs.iter().map(|addr| addr.into()).collect();
let server_types = listener.get_bootstraps(bind_addresses.clone());
for server_type in server_types {
servers.push(BrokerServerV0 {
peer_id,
server_type,
})
}
let listener_id: String = listener.to_string(); let listener_id: String = listener.to_string();
let listener_info = ListenerInfo { let listener_info = ListenerInfo {
config: listener, config: listener,
addrs: addrs.iter().map(|addr| addr.into()).collect(), addrs: bind_addresses,
}; };
listener_infos.insert(listener_id, listener_info); listener_infos.insert(listener_id, listener_info);
@ -598,11 +713,14 @@ pub async fn run_server_v0(
log_warn!("There isn't any listener that accept clients. This is a misconfiguration as a core server that cannot receive client connections is useless"); log_warn!("There isn't any listener that accept clients. This is a misconfiguration as a core server that cannot receive client connections is useless");
} }
let bootstrap = BootstrapContent::V0(BootstrapContentV0 { servers });
BOOTSTRAP_STRING.set(json!(bootstrap).to_string()).unwrap();
// saving the infos in the broker. This needs to happen before we start listening, as new incoming connections can happen anytime after that. // saving the infos in the broker. This needs to happen before we start listening, as new incoming connections can happen anytime after that.
// and we need those infos for permission checking. // and we need those infos for permission checking.
{ {
let mut broker = BROKER.write().await; let mut broker = BROKER.write().await;
broker.set_my_peer_id(peer_pub_key); broker.set_my_peer_id(peer_id);
LISTENERS_INFO LISTENERS_INFO
.set(broker.set_listeners(listener_infos)) .set(broker.set_listeners(listener_infos))
.unwrap(); .unwrap();

@ -33,4 +33,4 @@ features = ["js"]
[target.'cfg(not(target_arch = "wasm32"))'.dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
getrandom = "0.2.7" getrandom = "0.2.7"
xactor = "0.7.11" xactor = "0.7.11"
async-tungstenite = { version = "0.22.2", features = ["async-std-runtime"] } async-tungstenite = { git = "https://git.nextgraph.org/NextGraph/async-tungstenite.git", branch = "nextgraph", features = ["async-std-runtime"] }

@ -118,6 +118,18 @@ pub struct BrokerServerV0 {
pub peer_id: PubKey, pub peer_id: PubKey,
} }
/// Bootstrap content Version 0
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BootstrapContentV0 {
/// list of servers, in order of preference
pub servers: Vec<BrokerServerV0>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum BootstrapContent {
V0(BootstrapContentV0),
}
/// ListenerInfo /// ListenerInfo
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
@ -274,6 +286,61 @@ impl ListenerV0 {
accept_forward_for: AcceptForwardForV0::No, accept_forward_for: AcceptForwardForV0::No,
} }
} }
pub fn get_bootstraps(&self, addrs: Vec<BindAddress>) -> Vec<BrokerServerTypeV0> {
let mut res: Vec<BrokerServerTypeV0> = vec![];
match self.accept_forward_for {
AcceptForwardForV0::PublicStatic(_) => {
if !self.refuse_clients {
res.push(BrokerServerTypeV0::BoxPublic(
self.accept_forward_for.get_public_bind_addresses(),
));
}
if self.accept_direct {
res.push(BrokerServerTypeV0::BoxPrivate(addrs));
}
}
AcceptForwardForV0::PublicDyn(_) => {
if !self.refuse_clients {
res.push(BrokerServerTypeV0::BoxPublicDyn(
// self.accept_forward_for.get_public_bind_addresses(), //FIXME. we should use this, but for now it isnt implemented
vec![],
));
}
if self.accept_direct {
res.push(BrokerServerTypeV0::BoxPrivate(addrs));
}
}
AcceptForwardForV0::PublicDomain(_) | AcceptForwardForV0::PublicDomainPeer(_) => {
res.push(BrokerServerTypeV0::Domain(
self.accept_forward_for.get_domain().to_string(),
));
if self.accept_direct {
if self.if_type == InterfaceType::Private {
res.push(BrokerServerTypeV0::BoxPrivate(addrs));
} else if self.if_type == InterfaceType::Loopback {
res.push(BrokerServerTypeV0::Localhost(addrs[0].port));
}
}
}
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 && !self.refuse_clients {
res.push(BrokerServerTypeV0::BoxPublic(addrs));
} else if self.if_type == InterfaceType::Private {
res.push(BrokerServerTypeV0::BoxPrivate(addrs));
}
}
_ => panic!("get_bootstrap missing"),
}
res
}
} }
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
impl fmt::Display for ListenerV0 { impl fmt::Display for ListenerV0 {

@ -21,6 +21,7 @@ importers:
flowbite-svelte: ^0.37.1 flowbite-svelte: ^0.37.1
internal-ip: ^7.0.0 internal-ip: ^7.0.0
ng-sdk-js: workspace:^0.1.0 ng-sdk-js: workspace:^0.1.0
node-gzip: ^1.1.2
postcss: ^8.4.23 postcss: ^8.4.23
postcss-load-config: ^4.0.1 postcss-load-config: ^4.0.1
svelte: ^3.54.0 svelte: ^3.54.0
@ -53,6 +54,7 @@ importers:
autoprefixer: 10.4.14_postcss@8.4.24 autoprefixer: 10.4.14_postcss@8.4.24
cross-env: 7.0.3 cross-env: 7.0.3
internal-ip: 7.0.0 internal-ip: 7.0.0
node-gzip: 1.1.2
postcss: 8.4.24 postcss: 8.4.24
postcss-load-config: 4.0.1_postcss@8.4.24 postcss-load-config: 4.0.1_postcss@8.4.24
svelte: 3.59.1 svelte: 3.59.1
@ -72,12 +74,31 @@ importers:
ngone/web: ngone/web:
specifiers: specifiers:
'@sveltejs/vite-plugin-svelte': ^2.0.4 '@sveltejs/vite-plugin-svelte': ^2.0.4
autoprefixer: ^10.4.14
flowbite: ^1.6.5
flowbite-svelte: ^0.37.1
postcss: ^8.4.23
postcss-load-config: ^4.0.1
svelte: ^3.58.0 svelte: ^3.58.0
svelte-preprocess: ^5.0.3
svelte-spa-router: ^3.3.0
tailwindcss: ^3.3.1
vite: ^4.3.9 vite: ^4.3.9
vite-plugin-svelte-svg: ^2.2.1
dependencies:
flowbite: 1.6.5
flowbite-svelte: 0.37.3_svelte@3.59.1
svelte-spa-router: 3.3.0
devDependencies: devDependencies:
'@sveltejs/vite-plugin-svelte': 2.4.1_svelte@3.59.1+vite@4.3.9 '@sveltejs/vite-plugin-svelte': 2.4.1_svelte@3.59.1+vite@4.3.9
autoprefixer: 10.4.14_postcss@8.4.24
postcss: 8.4.24
postcss-load-config: 4.0.1_postcss@8.4.24
svelte: 3.59.1 svelte: 3.59.1
svelte-preprocess: 5.0.4_sxhny56dlbcmwov4vk7qwrzshi
tailwindcss: 3.3.2
vite: 4.3.9 vite: 4.3.9
vite-plugin-svelte-svg: 2.2.1_svelte@3.59.1+vite@4.3.9
packages: packages:
@ -1227,6 +1248,10 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true hasBin: true
/node-gzip/1.1.2:
resolution: {integrity: sha512-ZB6zWpfZHGtxZnPMrJSKHVPrRjURoUzaDbLFj3VO70mpLTW5np96vXyHwft4Id0o+PYIzgDkBUjIzaNHhQ8srw==}
dev: true
/node-releases/2.0.12: /node-releases/2.0.12:
resolution: {integrity: sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==} resolution: {integrity: sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==}
dev: true dev: true
@ -1631,6 +1656,54 @@ packages:
typescript: 5.1.3 typescript: 5.1.3
dev: true dev: true
/svelte-preprocess/5.0.4_sxhny56dlbcmwov4vk7qwrzshi:
resolution: {integrity: sha512-ABia2QegosxOGsVlsSBJvoWeXy1wUKSfF7SWJdTjLAbx/Y3SrVevvvbFNQqrSJw89+lNSsM58SipmZJ5SRi5iw==}
engines: {node: '>= 14.10.0'}
requiresBuild: true
peerDependencies:
'@babel/core': ^7.10.2
coffeescript: ^2.5.1
less: ^3.11.3 || ^4.0.0
postcss: ^7 || ^8
postcss-load-config: ^2.1.0 || ^3.0.0 || ^4.0.0
pug: ^3.0.0
sass: ^1.26.8
stylus: ^0.55.0
sugarss: ^2.0.0 || ^3.0.0 || ^4.0.0
svelte: ^3.23.0 || ^4.0.0-next.0 || ^4.0.0
typescript: '>=3.9.5 || ^4.0.0 || ^5.0.0'
peerDependenciesMeta:
'@babel/core':
optional: true
coffeescript:
optional: true
less:
optional: true
postcss:
optional: true
postcss-load-config:
optional: true
pug:
optional: true
sass:
optional: true
stylus:
optional: true
sugarss:
optional: true
typescript:
optional: true
dependencies:
'@types/pug': 2.0.6
detect-indent: 6.1.0
magic-string: 0.27.0
postcss: 8.4.24
postcss-load-config: 4.0.1_postcss@8.4.24
sorcery: 0.11.0
strip-indent: 3.0.0
svelte: 3.59.1
dev: true
/svelte-preprocess/5.0.4_vmz4xia4c7tzh4ii3qac2x3tom: /svelte-preprocess/5.0.4_vmz4xia4c7tzh4ii3qac2x3tom:
resolution: {integrity: sha512-ABia2QegosxOGsVlsSBJvoWeXy1wUKSfF7SWJdTjLAbx/Y3SrVevvvbFNQqrSJw89+lNSsM58SipmZJ5SRi5iw==} resolution: {integrity: sha512-ABia2QegosxOGsVlsSBJvoWeXy1wUKSfF7SWJdTjLAbx/Y3SrVevvvbFNQqrSJw89+lNSsM58SipmZJ5SRi5iw==}
engines: {node: '>= 14.10.0'} engines: {node: '>= 14.10.0'}

Loading…
Cancel
Save