metaverse_core 0.2.1

core program for server and client IO
use crate::session::Mailbox;
use crate::session::PingInfo;
use crate::transport::ui_event_listener::listen_for_ui_messages;
use actix::Actor;
use actix_rt::time;
use benthic_protocol::errors::SessionError;
use benthic_protocol::messages::ui::errors::MailboxSessionError;
use benthic_protocol::session::ServerState;
use benthic_protocol::session::initialize_share_dir;
use portpicker::pick_unused_port;
use std::collections::HashSet;
use std::sync::Arc;
use std::sync::Mutex;
use std::time::Duration;
use tokio::sync::Notify;
use tokio::task::JoinHandle;

/// This starts the mailbox, and blocks forever.
/// This should be run in its own thread, so as not to block anything else.
/// Also be sure that this is running within an actix system, or else it will fail silently.
pub async fn initialize(
    ui_to_server_socket: u16,
    server_to_ui_socket: u16,
) -> Result<JoinHandle<()>, SessionError> {
    let notify = Arc::new(Notify::new());
    let state = Arc::new(Mutex::new(ServerState::Starting));

    let share_dir = initialize_share_dir()?;
    let db_path = share_dir.join("inventory.db");
    let mailbox = Mailbox {
        client_socket: pick_unused_port().unwrap(),
        server_to_ui_socket: format!("127.0.0.1:{}", server_to_ui_socket),
        inventory_db_location: db_path,

        server_acks: HashSet::new(),
        viewer_acks: HashSet::new(),

        state: state.clone(),
        notify: notify.clone(),
        session: None,
        sent_packet_count: 0,
        ping_info: PingInfo {
            ping_number: 0,
            ping_latency: Duration::new(0, 0),
            last_ping: time::Instant::now(),
        },
    }
    .start();
    // wait until the mailbox starts
    notify.notified().await;
    if *state.lock().unwrap() != ServerState::Running {
        return Err(SessionError::MailboxSession(MailboxSessionError {
            message: ("Mailbox failed to enter state Running.".to_string()),
        }));
    };

    let handle = actix::spawn(async move {
        listen_for_ui_messages(format!("127.0.0.1:{}", ui_to_server_socket), mailbox).await;
    });

    Ok(handle)
}