Skip to content

Commit

Permalink
Merge pull request #208 from holochain/fix/holo-align-networking
Browse files Browse the repository at this point in the history
Align networking params with Holo
  • Loading branch information
matthme authored Aug 23, 2024
2 parents 9b18cb1 + e90f941 commit 6a3f2a5
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 127 deletions.
2 changes: 1 addition & 1 deletion rust-utils/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rust-utils/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
edition = "2021"
name = "hc-launcher-rust-utils"
version = "0.203.0"
version = "0.203.2"

[lib]
crate-type = ["cdylib"]
Expand Down
4 changes: 2 additions & 2 deletions rust-utils/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

/* auto-generated by NAPI-RS */

export function overwriteConfig(adminPort: number, keystoreConnectionUrl: string, bootstrapServerUrl: string | undefined | null, signalingServerUrl: string | undefined | null, configPath: string, allowedOrigin: string): string
export function defaultConductorConfig(adminPort: number, keystoreConnectionUrl: string, bootstrapServerUrl: string, signalingServerUrl: string, conductorEnvironmentPath: string, allowedOrigin: string): string
export function overwriteConfig(adminPort: number, keystoreConnectionUrl: string, bootstrapServerUrl: string | undefined | null, signalingServerUrl: string | undefined | null, configPath: string, allowedOrigin: string, iceServerUrls?: Array<string> | undefined | null): string
export function defaultConductorConfig(adminPort: number, keystoreConnectionUrl: string, bootstrapServerUrl: string, signalingServerUrl: string, conductorEnvironmentPath: string, allowedOrigin: string, iceServerUrls?: Array<string> | undefined | null): string
export function decodeHappOrWebhapp(happOrWebhappBytes: Array<number>): Promise<HappAndUiBytes>
export function readAndDecodeHappOrWebhapp(path: string): Promise<HappAndUiBytes>
export function saveWebhapp(path: string, uiTargetDir: string): Promise<string>
Expand Down
2 changes: 1 addition & 1 deletion rust-utils/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hc-launcher-rust-utils",
"version": "0.203.1",
"version": "0.203.2",
"main": "index.js",
"types": "index.d.ts",
"napi": {
Expand Down
303 changes: 184 additions & 119 deletions rust-utils/src/conductor_config.rs
Original file line number Diff line number Diff line change
@@ -1,150 +1,215 @@
#![deny(clippy::all)]

use holochain_conductor_api::{
conductor::{paths::DataRootPath, ConductorConfig, KeystoreConfig},
AdminInterfaceConfig, InterfaceDriver,
conductor::{paths::DataRootPath, ConductorConfig, KeystoreConfig},
AdminInterfaceConfig, InterfaceDriver,
};
use holochain_p2p::kitsune_p2p::dependencies::kitsune_p2p_types::config::{
tuning_params_struct::KitsuneP2pTuningParams, KitsuneP2pConfig, TransportConfig,
};
use holochain_p2p::kitsune_p2p::dependencies::kitsune_p2p_types::config::{tuning_params_struct::KitsuneP2pTuningParams, KitsuneP2pConfig, TransportConfig};
use holochain_types::websocket::AllowedOrigins;
use napi::{Error, Result, Status};
use napi_derive::napi;
use serde_yaml::{Mapping, Value};
use serde_yaml::{Mapping, Sequence, Value};
use std::{collections::HashSet, path::PathBuf};

fn create_error(msg: &str) -> Error {
Error::new(Status::GenericFailure, String::from(msg))
Error::new(Status::GenericFailure, String::from(msg))
}

fn insert_mapping(mapping: &mut Mapping, key: &str, value: Value) {
mapping.insert(Value::String(String::from(key)), value);
mapping.insert(Value::String(String::from(key)), value);
}

fn create_mapping_with_entries(entries: Vec<(&str, Value)>) -> Mapping {
let mut mapping = Mapping::new();
for (key, value) in entries {
insert_mapping(&mut mapping, key, value);
}
mapping
let mut mapping = Mapping::new();
for (key, value) in entries {
insert_mapping(&mut mapping, key, value);
}
mapping
}

fn webrtc_config_from_ice_urls(ice_server_urls: Vec<String>) -> serde_json::Value {
let mut webrtc_config = serde_json::Map::new();
let mut ice_servers = Vec::new();
for url in ice_server_urls {
let mut url_mapping = serde_json::Map::new();
url_mapping.insert(
String::from("urls"),
serde_json::Value::Array(vec![serde_json::Value::String(url)]),
);
ice_servers.push(serde_json::Value::Object(url_mapping));
}
webrtc_config.insert(
String::from("ice_servers"),
serde_json::Value::Array(ice_servers),
);
serde_json::Value::Object(webrtc_config)
}

#[napi]
pub fn overwrite_config(
admin_port: u16,
keystore_connection_url: String,
bootstrap_server_url: Option<String>,
signaling_server_url: Option<String>,
config_path: String,
allowed_origin: String,
admin_port: u16,
keystore_connection_url: String,
bootstrap_server_url: Option<String>,
signaling_server_url: Option<String>,
config_path: String,
allowed_origin: String,
ice_server_urls: Option<Vec<String>>,
) -> Result<String> {
let mut config = std::fs::read_to_string(&PathBuf::from(config_path))
.map_err(|_| create_error("Failed to read file"))
.and_then(|contents| {
serde_yaml::from_str::<Value>(&contents).map_err(|_| create_error("Failed to parse YAML"))
})
.and_then(|yaml| {
yaml
.as_mapping()
.cloned()
.ok_or_else(|| create_error("Expected YAML content to be a mapping"))
})?;

let websocket_interface = create_mapping_with_entries(vec![
("type", Value::String(String::from("websocket"))),
("port", Value::Number(admin_port.into())),
("allowed_origins", Value::String(allowed_origin)),
]);

let admin_interface =
create_mapping_with_entries(vec![("driver", Value::Mapping(websocket_interface))]);

insert_mapping(
&mut config,
"admin_interfaces",
Value::Sequence(vec![Value::Mapping(admin_interface)]),
);

insert_mapping(
&mut config,
"keystore",
Value::Mapping(create_mapping_with_entries(vec![
("type", Value::String(String::from("lair_server"))),
("connection_url", Value::String(keystore_connection_url)),
])),
);

let network = config
.get_mut(&Value::String(String::from("network")))
.and_then(|v| v.as_mapping_mut())
.ok_or_else(|| create_error("Expected 'network' entry in the config"))?;

bootstrap_server_url.map(|url| {
network.insert(
Value::String(String::from("bootstrap_service")),
Value::String(url),
let mut config = std::fs::read_to_string(&PathBuf::from(config_path))
.map_err(|_| create_error("Failed to read file"))
.and_then(|contents| {
serde_yaml::from_str::<Value>(&contents)
.map_err(|_| create_error("Failed to parse YAML"))
})
.and_then(|yaml| {
yaml.as_mapping()
.cloned()
.ok_or_else(|| create_error("Expected YAML content to be a mapping"))
})?;

let websocket_interface = create_mapping_with_entries(vec![
("type", Value::String(String::from("websocket"))),
("port", Value::Number(admin_port.into())),
("allowed_origins", Value::String(allowed_origin)),
]);

let admin_interface =
create_mapping_with_entries(vec![("driver", Value::Mapping(websocket_interface))]);

insert_mapping(
&mut config,
"admin_interfaces",
Value::Sequence(vec![Value::Mapping(admin_interface)]),
);

insert_mapping(
&mut config,
"keystore",
Value::Mapping(create_mapping_with_entries(vec![
("type", Value::String(String::from("lair_server"))),
("connection_url", Value::String(keystore_connection_url)),
])),
);
});

signaling_server_url.map(|url| {
let transport_pool = network
.entry(Value::String(String::from("transport_pool")))
.or_insert_with(|| Value::Sequence(Vec::new()));
if let Value::Sequence(transport_pool_seq) = transport_pool {
transport_pool_seq.clear(); // Clear existing transport pool entries
transport_pool_seq.push(Value::Mapping(create_mapping_with_entries(vec![
("type", Value::String(String::from("webrtc"))),
("signal_url", Value::String(url)),
])));

let network = config
.get_mut(&Value::String(String::from("network")))
.and_then(|v| v.as_mapping_mut())
.ok_or_else(|| create_error("Expected 'network' entry in the config"))?;

bootstrap_server_url.map(|url| {
network.insert(
Value::String(String::from("bootstrap_service")),
Value::String(url),
);
});

let mut webrtc_config = Mapping::new();
if let Some(ice_urls) = ice_server_urls.clone() {
let mut ice_servers = Sequence::new();
for url in ice_urls {
let mut url_mapping = Mapping::new();
let mut url_list = Sequence::new();
url_list.push(Value::String(url));
insert_mapping(&mut url_mapping, "urls", Value::Sequence(url_list));
ice_servers.push(Value::Mapping(url_mapping));
}
insert_mapping(
&mut webrtc_config,
"ice_servers",
Value::Sequence(ice_servers),
);
}
});

let _ = config
.get(&Value::String(String::from("network")))
.and_then(|v| v.as_mapping())
.and_then(|network| network.get(&Value::String(String::from("bootstrap_service"))))
.and_then(|v| v.as_str());
match (signaling_server_url.clone(), ice_server_urls.clone()) {
(None, None) => (),
_ => {
let transport_pool = network
.entry(Value::String(String::from("transport_pool")))
.or_insert_with(|| Value::Sequence(Vec::new()));

if let Value::Sequence(transport_pool_seq) = transport_pool {
let signaling_url = match signaling_server_url {
Some(url) => Value::String(url),
None => {
let tpool_element = transport_pool_seq.first();
match tpool_element {
Some(el) => el.get("signal_url").ok_or(napi::Error::from_reason("Conductor config did not contain a signaling server url."))?.to_owned(),
None => return Err(napi::Error::from_reason("Conductor config did not contain any element in the transport_pool section"))
}
}
};
transport_pool_seq.clear(); // Clear existing transport pool entries
let mut transport_pool_mapping = create_mapping_with_entries(vec![
("type", Value::String(String::from("webrtc"))),
("signal_url", signaling_url),
]);
if let Some(_) = ice_server_urls {
insert_mapping(
&mut transport_pool_mapping,
"webrtc_config",
Value::Mapping(webrtc_config),
);
}
transport_pool_seq.push(Value::Mapping(transport_pool_mapping));
}
}
}

serde_yaml::to_string(&config)
.map_err(|_| create_error("Could not convert conductor config to string"))
serde_yaml::to_string(&config)
.map_err(|_| create_error("Could not convert conductor config to string"))
}

#[napi]
pub fn default_conductor_config(
admin_port: u16,
keystore_connection_url: String,
bootstrap_server_url: String,
signaling_server_url: String,
conductor_environment_path: String,
allowed_origin: String,
admin_port: u16,
keystore_connection_url: String,
bootstrap_server_url: String,
signaling_server_url: String,
conductor_environment_path: String,
allowed_origin: String,
ice_server_urls: Option<Vec<String>>,
) -> Result<String> {
let mut network_config = KitsuneP2pConfig::default();
network_config.bootstrap_service = Some(url2::url2!("{}", bootstrap_server_url));

let tuning_params = KitsuneP2pTuningParams::default();
network_config.tuning_params = std::sync::Arc::new(tuning_params);

network_config.transport_pool.push(TransportConfig::WebRTC {
signal_url: signaling_server_url,
webrtc_config: None,
});

let mut allowed_origins_map = HashSet::new();
allowed_origins_map.insert(allowed_origin);

let config = ConductorConfig {
data_root_path: Some(DataRootPath::from(PathBuf::from(conductor_environment_path))),
dpki: None,
keystore: KeystoreConfig::LairServer {
connection_url: url2::url2!("{}", keystore_connection_url),
},
admin_interfaces: Some(vec![AdminInterfaceConfig {
driver: InterfaceDriver::Websocket { port: admin_port, allowed_origins: AllowedOrigins::Origins(allowed_origins_map) },
}]),
network: network_config,
db_sync_strategy: Default::default(),
tracing_override: None,
tuning_params: None,
};

serde_yaml::to_string(&config)
.map_err(|_| create_error("Failed to convert conductor config to yaml string."))
let mut network_config = KitsuneP2pConfig::default();
network_config.bootstrap_service = Some(url2::url2!("{}", bootstrap_server_url));

let tuning_params = KitsuneP2pTuningParams::default();
network_config.tuning_params = std::sync::Arc::new(tuning_params);

let webrtc_config = match ice_server_urls {
Some(urls) => Some(webrtc_config_from_ice_urls(urls)),
None => None,
};

network_config.transport_pool.push(TransportConfig::WebRTC {
signal_url: signaling_server_url,
webrtc_config,
});

let mut allowed_origins_map = HashSet::new();
allowed_origins_map.insert(allowed_origin);

let config = ConductorConfig {
data_root_path: Some(DataRootPath::from(PathBuf::from(
conductor_environment_path,
))),
dpki: None,
keystore: KeystoreConfig::LairServer {
connection_url: url2::url2!("{}", keystore_connection_url),
},
admin_interfaces: Some(vec![AdminInterfaceConfig {
driver: InterfaceDriver::Websocket {
port: admin_port,
allowed_origins: AllowedOrigins::Origins(allowed_origins_map),
},
}]),
network: network_config,
db_sync_strategy: Default::default(),
tracing_override: None,
tuning_params: None,
};

serde_yaml::to_string(&config)
.map_err(|_| create_error("Failed to convert conductor config to yaml string."))
}
Loading

0 comments on commit 6a3f2a5

Please sign in to comment.