|
@@ -1,5 +1,6 @@
|
|
// Code specific to the client in the client-server mode.
|
|
// Code specific to the client in the client-server mode.
|
|
|
|
|
|
|
|
+use futures::future::try_join_all;
|
|
use mgen::updater::Updater;
|
|
use mgen::updater::Updater;
|
|
use mgen::{log, HandshakeRef, MessageHeader, SerializedMessage};
|
|
use mgen::{log, HandshakeRef, MessageHeader, SerializedMessage};
|
|
use rand_xoshiro::{rand_core::SeedableRng, Xoshiro256PlusPlus};
|
|
use rand_xoshiro::{rand_core::SeedableRng, Xoshiro256PlusPlus};
|
|
@@ -7,9 +8,9 @@ use serde::Deserialize;
|
|
use std::result::Result;
|
|
use std::result::Result;
|
|
use std::sync::Arc;
|
|
use std::sync::Arc;
|
|
use tokio::io::{split, AsyncWriteExt, ReadHalf, WriteHalf};
|
|
use tokio::io::{split, AsyncWriteExt, ReadHalf, WriteHalf};
|
|
|
|
+use tokio::join;
|
|
use tokio::net::TcpStream;
|
|
use tokio::net::TcpStream;
|
|
use tokio::sync::mpsc;
|
|
use tokio::sync::mpsc;
|
|
-use tokio::task;
|
|
|
|
use tokio::time::Duration;
|
|
use tokio::time::Duration;
|
|
use tokio_rustls::{client::TlsStream, TlsConnector};
|
|
use tokio_rustls::{client::TlsStream, TlsConnector};
|
|
|
|
|
|
@@ -18,7 +19,8 @@ mod messenger;
|
|
use crate::messenger::dists::{ConfigDistributions, Distributions};
|
|
use crate::messenger::dists::{ConfigDistributions, Distributions};
|
|
use crate::messenger::error::{FatalError, MessengerError};
|
|
use crate::messenger::error::{FatalError, MessengerError};
|
|
use crate::messenger::state::{
|
|
use crate::messenger::state::{
|
|
- manage_active_conversation, manage_idle_conversation, StateMachine, StateToWriter,
|
|
+ manage_active_conversation, manage_idle_conversation, StateFromReader, StateMachine,
|
|
|
|
+ StateToWriter,
|
|
};
|
|
};
|
|
use crate::messenger::tcp::{connect, SocksParams};
|
|
use crate::messenger::tcp::{connect, SocksParams};
|
|
|
|
|
|
@@ -332,27 +334,63 @@ async fn socket_updater(
|
|
|
|
|
|
/// The thread responsible for handling the conversation state
|
|
/// The thread responsible for handling the conversation state
|
|
/// (i.e., whether the user is active or idle, and when to send messages).
|
|
/// (i.e., whether the user is active or idle, and when to send messages).
|
|
-/// Spawns all other threads for this conversation.
|
|
+async fn manage_conversation(
|
|
-async fn manage_conversation(config: FullConfig) -> Result<(), MessengerError> {
|
|
+ config: FullConfig,
|
|
|
|
+ mut state_from_reader: StateFromReader,
|
|
|
|
+ mut state_to_writer: StateToWriter<MessageHolder>,
|
|
|
|
+) {
|
|
|
|
+ tokio::time::sleep(Duration::from_secs_f64(config.bootstrap)).await;
|
|
|
|
+ log!("{},{},awake", &config.user, &config.group);
|
|
|
|
+
|
|
let mut rng = Xoshiro256PlusPlus::from_entropy();
|
|
let mut rng = Xoshiro256PlusPlus::from_entropy();
|
|
|
|
+ let mut state_machine = StateMachine::start(config.distributions, &mut rng);
|
|
|
|
+
|
|
|
|
+ loop {
|
|
|
|
+ state_machine = match state_machine {
|
|
|
|
+ StateMachine::Idle(conversation) => {
|
|
|
|
+ manage_idle_conversation::<false, _, _, _>(
|
|
|
|
+ conversation,
|
|
|
|
+ &mut state_from_reader,
|
|
|
|
+ &mut state_to_writer,
|
|
|
|
+ &config.user,
|
|
|
|
+ &config.group,
|
|
|
|
+ &mut rng,
|
|
|
|
+ )
|
|
|
|
+ .await
|
|
|
|
+ }
|
|
|
|
+ StateMachine::Active(conversation) => {
|
|
|
|
+ manage_active_conversation(
|
|
|
|
+ conversation,
|
|
|
|
+ &mut state_from_reader,
|
|
|
|
+ &mut state_to_writer,
|
|
|
|
+ &config.user,
|
|
|
|
+ &config.group,
|
|
|
|
+ false,
|
|
|
|
+ &mut rng,
|
|
|
|
+ )
|
|
|
|
+ .await
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
|
|
|
|
+/// Spawns all other threads for this conversation.
|
|
|
|
+async fn spawn_threads(config: FullConfig) -> Result<(), MessengerError> {
|
|
let message_server_params = SocksParams {
|
|
let message_server_params = SocksParams {
|
|
socks: config.socks.clone(),
|
|
socks: config.socks.clone(),
|
|
- target: config.message_server,
|
|
+ target: config.message_server.clone(),
|
|
user: config.user.clone(),
|
|
user: config.user.clone(),
|
|
recipient: config.group.clone(),
|
|
recipient: config.group.clone(),
|
|
};
|
|
};
|
|
|
|
|
|
let web_server_params = SocksParams {
|
|
let web_server_params = SocksParams {
|
|
- socks: config.socks,
|
|
+ socks: config.socks.clone(),
|
|
- target: config.web_server,
|
|
+ target: config.web_server.clone(),
|
|
user: config.user.clone(),
|
|
user: config.user.clone(),
|
|
recipient: config.group.clone(),
|
|
recipient: config.group.clone(),
|
|
};
|
|
};
|
|
|
|
|
|
- let mut state_machine = StateMachine::start(config.distributions, &mut rng);
|
|
+ let (reader_to_state, state_from_reader) = mpsc::unbounded_channel();
|
|
-
|
|
|
|
- let (reader_to_state, mut state_from_reader) = mpsc::unbounded_channel();
|
|
|
|
let (state_to_writer, writer_from_state) = mpsc::unbounded_channel();
|
|
let (state_to_writer, writer_from_state) = mpsc::unbounded_channel();
|
|
let read_socket_updater_in = Updater::new();
|
|
let read_socket_updater_in = Updater::new();
|
|
let read_socket_updater_out = read_socket_updater_in.clone();
|
|
let read_socket_updater_out = read_socket_updater_in.clone();
|
|
@@ -361,73 +399,48 @@ async fn manage_conversation(config: FullConfig) -> Result<(), MessengerError> {
|
|
let (errs_in, errs_out) = mpsc::unbounded_channel();
|
|
let (errs_in, errs_out) = mpsc::unbounded_channel();
|
|
let (writer_to_uploader, uploader_from_writer) = mpsc::unbounded_channel();
|
|
let (writer_to_uploader, uploader_from_writer) = mpsc::unbounded_channel();
|
|
|
|
|
|
|
|
+ let state_to_writer = StateToWriter {
|
|
|
|
+ channel: state_to_writer,
|
|
|
|
+ };
|
|
|
|
+
|
|
let retry = Duration::from_secs_f64(config.retry);
|
|
let retry = Duration::from_secs_f64(config.retry);
|
|
let tls_config = tokio_rustls::rustls::ClientConfig::builder()
|
|
let tls_config = tokio_rustls::rustls::ClientConfig::builder()
|
|
.with_safe_defaults()
|
|
.with_safe_defaults()
|
|
.with_custom_certificate_verifier(Arc::new(NoCertificateVerification {}))
|
|
.with_custom_certificate_verifier(Arc::new(NoCertificateVerification {}))
|
|
.with_no_client_auth();
|
|
.with_no_client_auth();
|
|
|
|
|
|
- tokio::spawn(reader(
|
|
+ let reader = reader(
|
|
web_server_params.clone(),
|
|
web_server_params.clone(),
|
|
retry,
|
|
retry,
|
|
tls_config.clone(),
|
|
tls_config.clone(),
|
|
reader_to_state,
|
|
reader_to_state,
|
|
read_socket_updater_out,
|
|
read_socket_updater_out,
|
|
errs_in.clone(),
|
|
errs_in.clone(),
|
|
- ));
|
|
+ );
|
|
- tokio::spawn(writer(
|
|
+ let writer = writer(
|
|
writer_from_state,
|
|
writer_from_state,
|
|
writer_to_uploader,
|
|
writer_to_uploader,
|
|
write_socket_updater_out,
|
|
write_socket_updater_out,
|
|
errs_in,
|
|
errs_in,
|
|
- ));
|
|
+ );
|
|
- tokio::spawn(uploader(
|
|
+ let uploader = uploader(
|
|
web_server_params,
|
|
web_server_params,
|
|
retry,
|
|
retry,
|
|
tls_config.clone(),
|
|
tls_config.clone(),
|
|
uploader_from_writer,
|
|
uploader_from_writer,
|
|
- ));
|
|
+ );
|
|
- tokio::spawn(socket_updater(
|
|
+ let updater = socket_updater(
|
|
message_server_params,
|
|
message_server_params,
|
|
retry,
|
|
retry,
|
|
tls_config,
|
|
tls_config,
|
|
errs_out,
|
|
errs_out,
|
|
read_socket_updater_in,
|
|
read_socket_updater_in,
|
|
write_socket_updater_in,
|
|
write_socket_updater_in,
|
|
- ));
|
|
+ );
|
|
-
|
|
+ let manager = manage_conversation(config, state_from_reader, state_to_writer);
|
|
- tokio::time::sleep(Duration::from_secs_f64(config.bootstrap)).await;
|
|
|
|
|
|
|
|
- let mut state_to_writer = StateToWriter {
|
|
+ join!(reader, writer, uploader, updater, manager);
|
|
- channel: state_to_writer,
|
|
+ Ok(())
|
|
- };
|
|
|
|
- loop {
|
|
|
|
- state_machine = match state_machine {
|
|
|
|
- StateMachine::Idle(conversation) => {
|
|
|
|
- manage_idle_conversation::<false, _, _, _>(
|
|
|
|
- conversation,
|
|
|
|
- &mut state_from_reader,
|
|
|
|
- &mut state_to_writer,
|
|
|
|
- &config.user,
|
|
|
|
- &config.group,
|
|
|
|
- &mut rng,
|
|
|
|
- )
|
|
|
|
- .await
|
|
|
|
- }
|
|
|
|
- StateMachine::Active(conversation) => {
|
|
|
|
- manage_active_conversation(
|
|
|
|
- conversation,
|
|
|
|
- &mut state_from_reader,
|
|
|
|
- &mut state_to_writer,
|
|
|
|
- &config.user,
|
|
|
|
- &config.group,
|
|
|
|
- false,
|
|
|
|
- &mut rng,
|
|
|
|
- )
|
|
|
|
- .await
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- }
|
|
|
|
}
|
|
}
|
|
|
|
|
|
struct FullConfig {
|
|
struct FullConfig {
|
|
@@ -463,8 +476,11 @@ struct Config {
|
|
conversations: Vec<ConversationConfig>,
|
|
conversations: Vec<ConversationConfig>,
|
|
}
|
|
}
|
|
|
|
|
|
-#[tokio::main(flavor = "multi_thread", worker_threads = 2)]
|
|
+#[tokio::main(flavor = "current_thread")]
|
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
|
+ #[cfg(feature = "tracing")]
|
|
|
|
+ console_subscriber::init();
|
|
|
|
+
|
|
let mut args = std::env::args();
|
|
let mut args = std::env::args();
|
|
let _ = args.next();
|
|
let _ = args.next();
|
|
let mut handles = vec![];
|
|
let mut handles = vec![];
|
|
@@ -491,16 +507,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
retry: conversation.retry.unwrap_or(config.retry),
|
|
retry: conversation.retry.unwrap_or(config.retry),
|
|
distributions,
|
|
distributions,
|
|
};
|
|
};
|
|
- let handle: task::JoinHandle<Result<(), MessengerError>> =
|
|
+ let handle = spawn_threads(filled_conversation);
|
|
- tokio::spawn(manage_conversation(filled_conversation));
|
|
|
|
handles.push(handle);
|
|
handles.push(handle);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- let handles: futures::stream::FuturesUnordered<_> = handles.into_iter().collect();
|
|
+ try_join_all(handles.into_iter()).await?;
|
|
- for handle in handles {
|
|
|
|
- handle.await??;
|
|
|
|
- }
|
|
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|