|
|
@ -1,22 +1,25 @@ |
|
|
|
use crate::chat::Chat; |
|
|
|
use crate::chat::Chat; |
|
|
|
use crate::gui_events::GuiEvent; |
|
|
|
use crate::gui_events::GuiEvent; |
|
|
|
use crate::message::{Profile, ProtocolMsg}; |
|
|
|
use crate::message::{Profile, ProtocolMsg}; |
|
|
|
|
|
|
|
use crate::DegMessage; |
|
|
|
use futures::Stream; |
|
|
|
use futures::Stream; |
|
|
|
use ironforce::res::IFResult; |
|
|
|
use ironforce::res::IFResult; |
|
|
|
use ironforce::{IronForce, Keys, Message, MessageType, PublicKey}; |
|
|
|
use ironforce::{IronForce, Keys, Message, MessageType, PublicKey}; |
|
|
|
|
|
|
|
use pyo3::prelude::*; |
|
|
|
|
|
|
|
use serde::{Deserialize, Serialize}; |
|
|
|
use std::pin::Pin; |
|
|
|
use std::pin::Pin; |
|
|
|
use std::sync::{Arc, Mutex}; |
|
|
|
use std::sync::{Arc, Mutex}; |
|
|
|
use std::task::{Context, Poll}; |
|
|
|
use std::task::{Context, Poll}; |
|
|
|
use pyo3::prelude::*; |
|
|
|
|
|
|
|
use serde::{Serialize, Deserialize}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// The container for logic, data, IF and protocol interactions
|
|
|
|
/// The container for logic, data, IF and protocol interactions
|
|
|
|
#[derive(Clone)] |
|
|
|
#[derive(Clone)] |
|
|
|
#[pyclass] |
|
|
|
#[pyclass] |
|
|
|
pub struct Degeon { |
|
|
|
pub struct Degeon { |
|
|
|
/// The list of all chats for this instance
|
|
|
|
/// The list of all chats for this instance
|
|
|
|
|
|
|
|
#[pyo3(get, set)] |
|
|
|
pub chats: Vec<Chat>, |
|
|
|
pub chats: Vec<Chat>, |
|
|
|
/// Profile of this user
|
|
|
|
/// Profile of this user
|
|
|
|
|
|
|
|
#[pyo3(get, set)] |
|
|
|
pub profile: Profile, |
|
|
|
pub profile: Profile, |
|
|
|
/// Keys of this user
|
|
|
|
/// Keys of this user
|
|
|
|
pub keys: Keys, |
|
|
|
pub keys: Keys, |
|
|
@ -46,12 +49,21 @@ fn get_initialized_ironforce() -> (Arc<Mutex<IronForce>>, Keys) { |
|
|
|
impl Default for Degeon { |
|
|
|
impl Default for Degeon { |
|
|
|
fn default() -> Self { |
|
|
|
fn default() -> Self { |
|
|
|
let (ironforce, keys) = get_initialized_ironforce(); |
|
|
|
let (ironforce, keys) = get_initialized_ironforce(); |
|
|
|
Self { |
|
|
|
let st = Self { |
|
|
|
chats: vec![], |
|
|
|
chats: vec![], |
|
|
|
profile: Profile::default(), |
|
|
|
profile: Profile::default(), |
|
|
|
keys, |
|
|
|
keys, |
|
|
|
ironforce, |
|
|
|
ironforce, |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
let self_clone = st.clone(); |
|
|
|
|
|
|
|
std::thread::spawn(move || { |
|
|
|
|
|
|
|
std::thread::sleep(std::time::Duration::from_secs(2)); |
|
|
|
|
|
|
|
loop { |
|
|
|
|
|
|
|
self_clone.send_multicast(ProtocolMsg::Ping).unwrap(); |
|
|
|
|
|
|
|
std::thread::sleep(std::time::Duration::from_secs(120)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
st |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -122,6 +134,7 @@ impl Degeon { |
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
println!("Sending: {:?}", msg); |
|
|
|
self.ironforce.lock().unwrap().send_to_all( |
|
|
|
self.ironforce.lock().unwrap().send_to_all( |
|
|
|
Message::build() |
|
|
|
Message::build() |
|
|
|
.message_type(MessageType::Broadcast) |
|
|
|
.message_type(MessageType::Broadcast) |
|
|
@ -162,6 +175,66 @@ impl Degeon { |
|
|
|
GuiEvent::None |
|
|
|
GuiEvent::None |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Process a GuiEvent if it's connected to the worker (like sending a message)
|
|
|
|
|
|
|
|
pub fn process_event(&mut self, event: &GuiEvent, perform_sending: bool) -> IFResult<()> { |
|
|
|
|
|
|
|
match event { |
|
|
|
|
|
|
|
GuiEvent::NewMessageInChat(pkey, msg) => { |
|
|
|
|
|
|
|
if self.chat_with(&pkey).is_none() { |
|
|
|
|
|
|
|
self.chats.push(Chat::new(pkey.clone())) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
let ind = self.chat_with(&pkey).unwrap(); |
|
|
|
|
|
|
|
self.chats[ind].messages.push(msg.clone()); |
|
|
|
|
|
|
|
self.save_to_file("".to_string())?; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
GuiEvent::SetProfile(pkey, profile) => { |
|
|
|
|
|
|
|
if self.chat_with(&pkey).is_none() { |
|
|
|
|
|
|
|
self.chats.push(Chat::new(pkey.clone())) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
let ind = self.chat_with(&pkey).unwrap(); |
|
|
|
|
|
|
|
self.chats[ind].profile = profile.clone(); |
|
|
|
|
|
|
|
self.save_to_file("".to_string())?; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
GuiEvent::WeHaveToSendProfile(target) if perform_sending => { |
|
|
|
|
|
|
|
let target = target.clone(); |
|
|
|
|
|
|
|
let self_cloned = self.clone(); |
|
|
|
|
|
|
|
std::thread::spawn(move || { |
|
|
|
|
|
|
|
self_cloned.send_message( |
|
|
|
|
|
|
|
ProtocolMsg::ProfileResponse(self_cloned.get_profile()), |
|
|
|
|
|
|
|
&target, |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
_ => {} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[pymethods] |
|
|
|
|
|
|
|
impl Degeon { |
|
|
|
|
|
|
|
/// Create a new text message and send it
|
|
|
|
|
|
|
|
pub fn send_text_message(&self, text: String, chat_i: usize) -> PyResult<()> { |
|
|
|
|
|
|
|
self.send_message( |
|
|
|
|
|
|
|
ProtocolMsg::NewMessage(DegMessage::new_text(text, &self.keys.get_public())), |
|
|
|
|
|
|
|
&self.chats[chat_i].pkey, |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
.map_err(|e| { |
|
|
|
|
|
|
|
pyo3::exceptions::PyTypeError::new_err(format!("There was an error in Rust: {:?}", e)) |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Handle one message
|
|
|
|
|
|
|
|
pub fn handling_loop_iteration(&mut self) { |
|
|
|
|
|
|
|
let event = self.read_message_and_create_event(); |
|
|
|
|
|
|
|
if let Some(event) = event { |
|
|
|
|
|
|
|
self.process_event(&event, true).unwrap_or_else(|e| println!("Error: {:?}", e)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn message_queue_len(&self) -> usize { |
|
|
|
|
|
|
|
self.ironforce.lock().unwrap().messages.len() |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub const DEFAULT_FILENAME: &str = ".degeon.json"; |
|
|
|
pub const DEFAULT_FILENAME: &str = ".degeon.json"; |
|
|
@ -190,7 +263,7 @@ impl Degeon { |
|
|
|
chats: data.chats, |
|
|
|
chats: data.chats, |
|
|
|
profile: data.profile, |
|
|
|
profile: data.profile, |
|
|
|
keys: data.keys, |
|
|
|
keys: data.keys, |
|
|
|
ironforce |
|
|
|
ironforce, |
|
|
|
}; |
|
|
|
}; |
|
|
|
Ok(deg) |
|
|
|
Ok(deg) |
|
|
|
} |
|
|
|
} |
|
|
@ -219,11 +292,8 @@ impl Degeon { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl Stream for Degeon { |
|
|
|
impl Degeon { |
|
|
|
type Item = GuiEvent; |
|
|
|
pub fn read_message_and_create_event(&self) -> Option<GuiEvent> { |
|
|
|
|
|
|
|
|
|
|
|
fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { |
|
|
|
|
|
|
|
let timestamp_0 = std::time::Instant::now(); |
|
|
|
|
|
|
|
let msg_raw = self.ironforce.lock().unwrap().read_message(); |
|
|
|
let msg_raw = self.ironforce.lock().unwrap().read_message(); |
|
|
|
let msg = msg_raw |
|
|
|
let msg = msg_raw |
|
|
|
.as_ref() |
|
|
|
.as_ref() |
|
|
@ -240,18 +310,27 @@ impl Stream for Degeon { |
|
|
|
Ok(r) => r, |
|
|
|
Ok(r) => r, |
|
|
|
Err(_) => { |
|
|
|
Err(_) => { |
|
|
|
println!("Couldn't deserialize {:?}", msg_raw); |
|
|
|
println!("Couldn't deserialize {:?}", msg_raw); |
|
|
|
return Poll::Ready(Some(GuiEvent::None)); |
|
|
|
return Some(GuiEvent::None); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
println!("{:?} -> {:?}", msg_deg, msg); |
|
|
|
println!("{:?} -> {:?}", msg_deg, msg); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
match msg { |
|
|
|
|
|
|
|
Some(Some(event)) => Some(event), |
|
|
|
|
|
|
|
_ => None |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl Stream for Degeon { |
|
|
|
|
|
|
|
type Item = GuiEvent; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { |
|
|
|
|
|
|
|
let timestamp_0 = std::time::Instant::now(); |
|
|
|
|
|
|
|
let msg = self.read_message_and_create_event(); |
|
|
|
if timestamp_0.elapsed() < std::time::Duration::from_millis(5) { |
|
|
|
if timestamp_0.elapsed() < std::time::Duration::from_millis(5) { |
|
|
|
std::thread::sleep(std::time::Duration::from_millis(5)); |
|
|
|
std::thread::sleep(std::time::Duration::from_millis(5)); |
|
|
|
} |
|
|
|
} |
|
|
|
match msg { |
|
|
|
Poll::Ready(Some(msg.unwrap_or(GuiEvent::None))) |
|
|
|
None => Poll::Ready(Some(GuiEvent::None)), |
|
|
|
|
|
|
|
Some(None) => Poll::Ready(Some(GuiEvent::None)), |
|
|
|
|
|
|
|
Some(Some(msg)) => Poll::Ready(Some(msg)), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |