|
|
@@ -51,6 +51,7 @@ use log::LevelFilter;
|
|
|
|
|
|
mod app;
|
|
|
mod darkirc;
|
|
|
+use darkirc::DarkIrcBackend;
|
|
|
//mod chatapp;
|
|
|
//mod chatview;
|
|
|
//mod editbox;
|
|
|
@@ -78,11 +79,6 @@ use crate::{
|
|
|
text2::TextShaper,
|
|
|
};
|
|
|
|
|
|
-#[cfg(target_os = "android")]
|
|
|
-const EVGRDB_PATH: &str = "/data/data/darkfi.darkwallet/evgrdb/";
|
|
|
-#[cfg(target_os = "linux")]
|
|
|
-const EVGRDB_PATH: &str = "evgrdb";
|
|
|
-
|
|
|
pub type ExecutorPtr = Arc<smol::Executor<'static>>;
|
|
|
|
|
|
fn panic_hook(panic_info: &std::panic::PanicInfo) {
|
|
|
@@ -91,280 +87,6 @@ fn panic_hook(panic_info: &std::panic::PanicInfo) {
|
|
|
std::process::exit(1);
|
|
|
}
|
|
|
|
|
|
-#[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
|
|
|
-pub struct Privmsg {
|
|
|
- pub channel: String,
|
|
|
- pub nick: String,
|
|
|
- pub msg: String,
|
|
|
-}
|
|
|
-
|
|
|
-async fn relay_darkirc_events(sg: SceneGraphPtr2, ev_sub: Subscription<event_graph::Event>) {
|
|
|
- loop {
|
|
|
- let ev = ev_sub.receive().await;
|
|
|
-
|
|
|
- // Try to deserialize the `Event`'s content into a `Privmsg`
|
|
|
- let mut privmsg: Privmsg = match deserialize_async(ev.content()).await {
|
|
|
- Ok(v) => v,
|
|
|
- Err(e) => {
|
|
|
- error!("[IRC CLIENT] Failed deserializing incoming Privmsg event: {}", e);
|
|
|
- continue
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- if privmsg.channel != "#random" {
|
|
|
- continue
|
|
|
- }
|
|
|
-
|
|
|
- info!(target: "main", "ev_id={:?}", ev.id());
|
|
|
- info!(target: "main", "ev: {:?}", ev);
|
|
|
- info!(target: "main", "privmsg: {:?}", privmsg);
|
|
|
- info!(target: "main", "");
|
|
|
-
|
|
|
- let response_fn = Box::new(|_| {});
|
|
|
-
|
|
|
- let mut arg_data = vec![];
|
|
|
- ev.timestamp.encode(&mut arg_data);
|
|
|
- ev.id().as_bytes().encode(&mut arg_data);
|
|
|
- privmsg.nick.encode(&mut arg_data);
|
|
|
- privmsg.msg.encode(&mut arg_data);
|
|
|
-
|
|
|
- let mut sg = sg.lock().await;
|
|
|
- let chatview_node = sg.lookup_node_mut("/window/view/chatty").unwrap();
|
|
|
- chatview_node.call_method("insert_line", arg_data, response_fn).unwrap();
|
|
|
- drop(sg);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-async fn run_darkirc_backend(sg: SceneGraphPtr2, ex: ExecutorPtr) -> darkfi::Result<()> {
|
|
|
- info!(target: "main", "Starting DarkIRC backend");
|
|
|
- let sled_db = sled::open(EVGRDB_PATH)?;
|
|
|
-
|
|
|
- let mut p2p_settings: NetSettings = Default::default();
|
|
|
- p2p_settings.app_version = semver::Version::parse("0.5.0").unwrap();
|
|
|
- p2p_settings.seeds.push(url::Url::parse("tcp+tls://lilith1.dark.fi:5262").unwrap());
|
|
|
-
|
|
|
- let p2p = P2p::new(p2p_settings, ex.clone()).await?;
|
|
|
-
|
|
|
- let event_graph = EventGraph::new(
|
|
|
- p2p.clone(),
|
|
|
- sled_db.clone(),
|
|
|
- std::path::PathBuf::new(),
|
|
|
- false,
|
|
|
- "darkirc_dag",
|
|
|
- 1,
|
|
|
- ex.clone(),
|
|
|
- )
|
|
|
- .await?;
|
|
|
-
|
|
|
- let prune_task = event_graph.prune_task.get().unwrap();
|
|
|
-
|
|
|
- info!(target: "main", "Registering EventGraph P2P protocol");
|
|
|
- let event_graph_ = Arc::clone(&event_graph);
|
|
|
- let registry = p2p.protocol_registry();
|
|
|
- registry
|
|
|
- .register(SESSION_DEFAULT, move |channel, _| {
|
|
|
- let event_graph_ = event_graph_.clone();
|
|
|
- async move { ProtocolEventGraph::init(event_graph_, channel).await.unwrap() }
|
|
|
- })
|
|
|
- .await;
|
|
|
-
|
|
|
- let ev_sub = event_graph.event_pub.clone().subscribe().await;
|
|
|
- let ev_task = ex.spawn(relay_darkirc_events(sg, ev_sub));
|
|
|
-
|
|
|
- info!(target: "main", "Starting P2P network");
|
|
|
- p2p.clone().start().await?;
|
|
|
-
|
|
|
- info!(target: "main", "Waiting for some P2P connections...");
|
|
|
- sleep(5).await;
|
|
|
-
|
|
|
- // We'll attempt to sync {sync_attempts} times
|
|
|
- let sync_attempts = 4;
|
|
|
- for i in 1..=sync_attempts {
|
|
|
- info!(target: "main", "Syncing event DAG (attempt #{})", i);
|
|
|
- match event_graph.dag_sync().await {
|
|
|
- Ok(()) => break,
|
|
|
- Err(e) => {
|
|
|
- if i == sync_attempts {
|
|
|
- error!("Failed syncing DAG. Exiting.");
|
|
|
- p2p.stop().await;
|
|
|
- return Err(Error::DagSyncFailed)
|
|
|
- } else {
|
|
|
- // TODO: Maybe at this point we should prune or something?
|
|
|
- // TODO: Or maybe just tell the user to delete the DAG from FS.
|
|
|
- error!("Failed syncing DAG ({}), retrying in {}s...", e, 4);
|
|
|
- sleep(4).await;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- sleep_forever().await;
|
|
|
- // Signal handling for graceful termination.
|
|
|
- //let (signals_handler, signals_task) = SignalHandler::new(ex)?;
|
|
|
- //signals_handler.wait_termination(signals_task).await?;
|
|
|
- info!(target: "main", "Caught termination signal, cleaning up and exiting...");
|
|
|
-
|
|
|
- info!(target: "main", "Stopping P2P network");
|
|
|
- p2p.stop().await;
|
|
|
-
|
|
|
- info!(target: "main", "Stopping IRC server");
|
|
|
- prune_task.stop().await;
|
|
|
-
|
|
|
- info!(target: "main", "Flushing sled database...");
|
|
|
- let flushed_bytes = sled_db.flush_async().await?;
|
|
|
- info!(target: "main", "Flushed {} bytes", flushed_bytes);
|
|
|
-
|
|
|
- info!(target: "main", "Shut down successfully");
|
|
|
-
|
|
|
- Ok(())
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
-fn newmain() {
|
|
|
- simplelog::TermLogger::init(
|
|
|
- simplelog::LevelFilter::Info,
|
|
|
- simplelog::Config::default(),
|
|
|
- simplelog::TerminalMode::Stdout,
|
|
|
- simplelog::ColorChoice::Auto,
|
|
|
- )
|
|
|
- .unwrap();
|
|
|
-
|
|
|
- let ex = Arc::new(smol::Executor::new());
|
|
|
- let n_threads = std::thread::available_parallelism().unwrap().get();
|
|
|
- let ex = std::sync::Arc::new(smol::Executor::new());
|
|
|
- let (signal, shutdown) = smol::channel::unbounded::<()>();
|
|
|
- let (_, result) = easy_parallel::Parallel::new()
|
|
|
- // Run four executor threads
|
|
|
- .each(0..n_threads, |_| smol::future::block_on(ex.run(shutdown.recv())))
|
|
|
- // Run the main future on the current thread.
|
|
|
- .finish(|| {
|
|
|
- smol::future::block_on(async {
|
|
|
- run_darkirc_backend(ex.clone()).await?;
|
|
|
- drop(signal);
|
|
|
- Ok::<(), darkfi::Error>(())
|
|
|
- })
|
|
|
- });
|
|
|
-}
|
|
|
-*/
|
|
|
-
|
|
|
-type DarkIrcBackendPtr = Arc<DarkIrcBackend>;
|
|
|
-
|
|
|
-struct DarkIrcData {
|
|
|
- p2p: P2pPtr,
|
|
|
- event_graph: EventGraphPtr,
|
|
|
- ev_task: smol::Task<()>,
|
|
|
- db: sled::Db,
|
|
|
-}
|
|
|
-
|
|
|
-struct DarkIrcBackend(SyncMutex<Option<DarkIrcData>>);
|
|
|
-
|
|
|
-impl DarkIrcBackend {
|
|
|
- fn new() -> Arc<Self> {
|
|
|
- Arc::new(Self(SyncMutex::new(None)))
|
|
|
- }
|
|
|
-
|
|
|
- async fn start(&self, sg: SceneGraphPtr2, ex: ExecutorPtr) -> darkfi::Result<()> {
|
|
|
- info!(target: "main", "Starting DarkIRC backend");
|
|
|
- let sled_db = sled::open(EVGRDB_PATH)?;
|
|
|
-
|
|
|
- let mut p2p_settings: NetSettings = Default::default();
|
|
|
- p2p_settings.app_version = semver::Version::parse("0.5.0").unwrap();
|
|
|
- p2p_settings.seeds.push(url::Url::parse("tcp+tls://lilith1.dark.fi:5262").unwrap());
|
|
|
-
|
|
|
- let p2p = P2p::new(p2p_settings, ex.clone()).await?;
|
|
|
-
|
|
|
- let event_graph = EventGraph::new(
|
|
|
- p2p.clone(),
|
|
|
- sled_db.clone(),
|
|
|
- std::path::PathBuf::new(),
|
|
|
- false,
|
|
|
- "darkirc_dag",
|
|
|
- 1,
|
|
|
- ex.clone(),
|
|
|
- )
|
|
|
- .await?;
|
|
|
-
|
|
|
- //self.prune_task.lock().unwrap() = Some(event_graph.prune_task.get().unwrap());
|
|
|
-
|
|
|
- info!(target: "main", "Registering EventGraph P2P protocol");
|
|
|
- let event_graph_ = Arc::clone(&event_graph);
|
|
|
- let registry = p2p.protocol_registry();
|
|
|
- registry
|
|
|
- .register(SESSION_DEFAULT, move |channel, _| {
|
|
|
- let event_graph_ = event_graph_.clone();
|
|
|
- async move { ProtocolEventGraph::init(event_graph_, channel).await.unwrap() }
|
|
|
- })
|
|
|
- .await;
|
|
|
-
|
|
|
- let ev_sub = event_graph.event_pub.clone().subscribe().await;
|
|
|
- let ev_task = ex.spawn(relay_darkirc_events(sg, ev_sub));
|
|
|
-
|
|
|
- info!(target: "main", "Starting P2P network");
|
|
|
- p2p.clone().start().await?;
|
|
|
-
|
|
|
- info!(target: "main", "Waiting for some P2P connections...");
|
|
|
- sleep(5).await;
|
|
|
-
|
|
|
- // We'll attempt to sync {sync_attempts} times
|
|
|
- let sync_attempts = 4;
|
|
|
- for i in 1..=sync_attempts {
|
|
|
- info!(target: "main", "Syncing event DAG (attempt #{})", i);
|
|
|
- match event_graph.dag_sync().await {
|
|
|
- Ok(()) => break,
|
|
|
- Err(e) => {
|
|
|
- if i == sync_attempts {
|
|
|
- error!("Failed syncing DAG. Exiting.");
|
|
|
- p2p.stop().await;
|
|
|
- return Err(Error::DagSyncFailed)
|
|
|
- } else {
|
|
|
- // TODO: Maybe at this point we should prune or something?
|
|
|
- // TODO: Or maybe just tell the user to delete the DAG from FS.
|
|
|
- error!("Failed syncing DAG ({}), retrying in {}s...", e, 4);
|
|
|
- sleep(4).await;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- *self.0.lock().unwrap() = Some(DarkIrcData { p2p, event_graph, ev_task, db: sled_db });
|
|
|
-
|
|
|
- Ok(())
|
|
|
- }
|
|
|
-
|
|
|
- async fn stop(&self) {
|
|
|
- info!(target: "main", "Stopping DarkIRC backend");
|
|
|
- let self_ = self.0.lock().unwrap();
|
|
|
- let Some(self_) = &*self_ else {
|
|
|
- warn!(target: "main", "Backend wasn't started");
|
|
|
- return
|
|
|
- };
|
|
|
-
|
|
|
- info!(target: "main", "Stopping P2P network");
|
|
|
- self_.p2p.stop().await;
|
|
|
-
|
|
|
- info!(target: "main", "Stopping IRC server");
|
|
|
- let prune_task = self_.event_graph.prune_task.get().unwrap();
|
|
|
- prune_task.stop().await;
|
|
|
-
|
|
|
- info!(target: "main", "Flushing event graph sled database...");
|
|
|
- let Ok(flushed_bytes) = self_.db.flush_async().await else {
|
|
|
- error!(target: "main", "Flushing event graph db failed");
|
|
|
- return
|
|
|
- };
|
|
|
- info!(target: "main", "Flushed {} bytes", flushed_bytes);
|
|
|
- info!(target: "main", "Shut down backend successfully");
|
|
|
- }
|
|
|
-
|
|
|
- async fn send(&self, privmsg: Privmsg) {
|
|
|
- let evgr =
|
|
|
- self.0.lock().unwrap().as_ref().expect("backend wasnt started").event_graph.clone();
|
|
|
- let event = event_graph::Event::new(serialize_async(&privmsg).await, &evgr).await;
|
|
|
- if let Err(e) = evgr.dag_insert(&[event]).await {
|
|
|
- error!(target: "main", "Failed inserting new event to DAG: {}", e);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
fn main() {
|
|
|
// Exit the application on panic right away
|
|
|
std::panic::set_hook(Box::new(panic_hook));
|