[Core] WIP: Sessions

This commit is contained in:
ashthespy 2021-01-23 22:21:42 +00:00
parent 20dd94fe20
commit 0892587c0e

View file

@ -10,13 +10,7 @@ use bytes::Bytes;
// use tokio::runtime::{current_thread, current_thread::Handle}; // use tokio::runtime::{current_thread, current_thread::Handle};
// use futures::future::{IntoFuture, Remote}; // use futures::future::{IntoFuture, Remote};
use futures::{ use futures::{channel::mpsc, future, Future, Stream, StreamExt, TryFutureExt};
channel::mpsc,
// future::{IntoFuture, Remote},
Future,
Stream,
TryFutureExt,
};
use std::{ use std::{
pin::Pin, pin::Pin,
task::{Context, Poll}, task::{Context, Poll},
@ -25,14 +19,14 @@ use std::{
use tokio::runtime::Handle; use tokio::runtime::Handle;
use crate::apresolve::apresolve_or_fallback; use crate::apresolve::apresolve_or_fallback;
use crate::audio_key::AudioKeyManager; // use crate::audio_key::AudioKeyManager;
use crate::authentication::Credentials; use crate::authentication::Credentials;
use crate::cache::Cache; use crate::cache::Cache;
use crate::channel::ChannelManager; // use crate::channel::ChannelManager;
use crate::component::Lazy; // use crate::component::Lazy;
use crate::config::SessionConfig; use crate::config::SessionConfig;
use crate::connection; use crate::connection;
use crate::mercury::MercuryManager; // use crate::mercury::MercuryManager;
struct SessionData { struct SessionData {
country: String, country: String,
@ -45,13 +39,12 @@ struct SessionInternal {
config: SessionConfig, config: SessionConfig,
data: RwLock<SessionData>, data: RwLock<SessionData>,
tx_connection: mpsc::UnboundedSender<(u8, Vec<u8>)>, tx_connection: mpsc::UnboundedSender<io::Result<(u8, Vec<u8>)>>,
audio_key: Lazy<AudioKeyManager>, // audio_key: Lazy<AudioKeyManager>,
channel: Lazy<ChannelManager>, // channel: Lazy<ChannelManager>,
mercury: Lazy<MercuryManager>, // mercury: Lazy<MercuryManager>,
cache: Option<Arc<Cache>>, cache: Option<Arc<Cache>>,
handle: Mutex<Handle>, handle: Mutex<Handle>,
session_id: usize, session_id: usize,
} }
@ -71,42 +64,44 @@ impl Session {
cache: Option<Cache>, cache: Option<Cache>,
handle: Handle, handle: Handle,
) -> Result<Session> { ) -> Result<Session> {
unimplemented!() let access_point_addr =
// let access_point_addr = apresolve_or_fallback::<io::Error>(&config.proxy, &config.ap_port).await?;
// apresolve_or_fallback::<io::Error>(&config.proxy, &config.ap_port).await?;
// let proxy = config.proxy.clone();
// let proxy = config.proxy.clone(); info!("Connecting to AP \"{}\"", access_point_addr);
// info!("Connecting to AP \"{}\"", access_point_addr); let connection = connection::connect(access_point_addr, &proxy);
// let connection = connection::connect(access_point_addr, &proxy);
// let device_id = config.device_id.clone();
// let device_id = config.device_id.clone(); let authentication = connection.and_then(move |connection| {
// let authentication = connection.and_then(move |connection| { connection::authenticate(connection, credentials, device_id)
// connection::authenticate(connection, credentials, device_id) });
// });
// let result = match authentication.await {
// let result = authentication.map(move |(transport, reusable_credentials)| { Ok((transport, reusable_credentials)) => {
// info!("Authenticated as \"{}\" !", reusable_credentials.username); info!("Authenticated as \"{}\" !", reusable_credentials.username);
// if let Some(ref cache) = cache { if let Some(ref cache) = cache {
// cache.save_credentials(&reusable_credentials); cache.save_credentials(&reusable_credentials);
// } }
//
// let (session, task) = Session::create( let (session, tasks) = Session::create(
// &handle, &handle,
// transport, transport,
// config, config,
// cache, cache,
// reusable_credentials.username.clone(), reusable_credentials.username.clone(),
// ); );
//
// tokio::spawn(task.map_err(|e| { tokio::task::spawn_local(async move { tasks });
// error!("SessionError: {}", e.to_string());
// std::process::exit(0); Ok(session)
// })); }
// Err(e) => {
// session error!("Unable to Connect");
// }); Err(e.into())
// }
// result };
result
} }
fn create( fn create(
@ -115,7 +110,7 @@ impl Session {
config: SessionConfig, config: SessionConfig,
cache: Option<Cache>, cache: Option<Cache>,
username: String, username: String,
) -> (Session, Box<dyn Future<Output = Result<()>>>) { ) -> (Session, Box<dyn Future<Output = (Result<()>, Result<()>)>>) {
let (sink, stream) = transport.split(); let (sink, stream) = transport.split();
let (sender_tx, sender_rx) = mpsc::unbounded(); let (sender_tx, sender_rx) = mpsc::unbounded();
@ -124,7 +119,7 @@ impl Session {
debug!("new Session[{}]", session_id); debug!("new Session[{}]", session_id);
let session = Session(Arc::new(SessionInternal { let session = Session(Arc::new(SessionInternal {
config: config, config,
data: RwLock::new(SessionData { data: RwLock::new(SessionData {
country: String::new(), country: String::new(),
canonical_username: username, canonical_username: username,
@ -136,57 +131,52 @@ impl Session {
cache: cache.map(Arc::new), cache: cache.map(Arc::new),
audio_key: Lazy::new(), // audio_key: Lazy::new(),
channel: Lazy::new(), // channel: Lazy::new(),
mercury: Lazy::new(), // mercury: Lazy::new(),
handle: Mutex::new(handle.clone()), handle: Mutex::new(handle.clone()),
session_id: session_id, session_id,
})); }));
let sender_task = sender_rx let sender_task = sender_rx
.map_err(|e| -> io::Error { panic!(e) })
.forward(sink) .forward(sink)
.map(|_| ()); .map_err(|e| -> Box<dyn std::error::Error> { Box::new(e) });
let receiver_task = DispatchTask(stream, session.weak()); let receiver_task = DispatchTask(stream, session.weak());
let task = Box::new( let task = Box::new(future::join(receiver_task, sender_task));
(receiver_task, sender_task)
.into_future()
.map(|((), ())| ()),
);
(session, task) (session, task)
} }
pub fn audio_key(&self) -> &AudioKeyManager { // pub fn audio_key(&self) -> &AudioKeyManager {
self.0.audio_key.get(|| AudioKeyManager::new(self.weak())) // self.0.audio_key.get(|| AudioKeyManager::new(self.weak()))
} // }
pub fn channel(&self) -> &ChannelManager { // pub fn channel(&self) -> &ChannelManager {
self.0.channel.get(|| ChannelManager::new(self.weak())) // self.0.channel.get(|| ChannelManager::new(self.weak()))
} // }
pub fn mercury(&self) -> &MercuryManager { // pub fn mercury(&self) -> &MercuryManager {
self.0.mercury.get(|| MercuryManager::new(self.weak())) // self.0.mercury.get(|| MercuryManager::new(self.weak()))
} // }
pub fn time_delta(&self) -> i64 { pub fn time_delta(&self) -> i64 {
self.0.data.read().unwrap().time_delta self.0.data.read().unwrap().time_delta
} }
// Spawn a future directly // Spawn a future directly
pub fn spawn<F>(&self, f: F) // pub fn spawn<F>(&self, f: F)
where // where
F: Future<Output = ()> + Send + 'static, // F: Future<Output = ()> + Send + 'static,
{ // {
let handle = self.0.handle.lock().unwrap(); // let handle = self.0.handle.lock().unwrap();
let spawn_res = handle.spawn(f); // let spawn_res = handle.spawn(f);
match spawn_res { // match spawn_res {
Ok(_) => (), // Ok(_) => (),
Err(e) => error!("Session SpawnErr {:?}", e), // Err(e) => error!("Session SpawnErr {:?}", e),
} // }
} // }
// pub fn spawn<F, R>(&self, f: F) // pub fn spawn<F, R>(&self, f: F)
// where // where
@ -218,7 +208,7 @@ impl Session {
); );
} }
#[cfg_attr(feature = "cargo-clippy", allow(match_same_arms))] // #[cfg_attr(feature = "cargo-clippy", allow(match_same_arms))]
fn dispatch(&self, cmd: u8, data: Bytes) { fn dispatch(&self, cmd: u8, data: Bytes) {
match cmd { match cmd {
0x4 => { 0x4 => {
@ -241,15 +231,18 @@ impl Session {
self.0.data.write().unwrap().country = country; self.0.data.write().unwrap().country = country;
} }
0x9 | 0xa => self.channel().dispatch(cmd, data), // 0x9 | 0xa => self.channel().dispatch(cmd, data),
0xd | 0xe => self.audio_key().dispatch(cmd, data), // 0xd | 0xe => self.audio_key().dispatch(cmd, data),
0xb2..=0xb6 => self.mercury().dispatch(cmd, data), // 0xb2..=0xb6 => self.mercury().dispatch(cmd, data),
_ => trace!("Unknown dispatch cmd :{:?} {:?}", cmd, data), _ => trace!("Unknown dispatch cmd :{:?} {:?}", cmd, data),
} }
} }
pub fn send_packet(&self, cmd: u8, data: Vec<u8>) { pub fn send_packet(&self, cmd: u8, data: Vec<u8>) {
self.0.tx_connection.unbounded_send((cmd, data)).unwrap(); self.0
.tx_connection
.unbounded_send(Ok((cmd, data)))
.unwrap();
} }
pub fn cache(&self) -> Option<&Arc<Cache>> { pub fn cache(&self) -> Option<&Arc<Cache>> {
@ -283,8 +276,8 @@ impl Session {
pub fn shutdown(&self) { pub fn shutdown(&self) {
debug!("Invalidating session[{}]", self.0.session_id); debug!("Invalidating session[{}]", self.0.session_id);
self.0.data.write().unwrap().invalid = true; self.0.data.write().unwrap().invalid = true;
self.mercury().shutdown(); // self.mercury().shutdown();
self.channel().shutdown(); // self.channel().shutdown();
} }
pub fn is_invalid(&self) -> bool { pub fn is_invalid(&self) -> bool {
@ -311,40 +304,37 @@ impl Drop for SessionInternal {
} }
} }
// type SErr = ::std::fmt::Debug;
struct DispatchTask<S>(S, SessionWeak) struct DispatchTask<S>(S, SessionWeak)
where where
S: Stream<Item = Result<((u8, Bytes), ())>>; S: Stream<Item = io::Result<(u8, Bytes)>> + Unpin;
impl<S> Future for DispatchTask<S> impl<S: Stream<Item = io::Result<(u8, Bytes)>>> Future for DispatchTask<S>
where where
// SErr: ::std::fmt::Debug, S: Stream<Item = io::Result<(u8, Bytes)>> + Unpin,
S: Stream<Item = Result<((u8, Bytes), ())>>,
{ {
type Output = Result<((), ())>; type Output = Result<()>;
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let session = match self.1.try_upgrade() { let session = match self.1.try_upgrade() {
Some(session) => session, Some(session) => session,
None => return Poll::Ready(()), None => return Poll::Ready(Ok(())),
}; };
loop { loop {
let (cmd, data) = match self.unwrap().0.poll() { let (cmd, data) = match Pin::new(&mut self.0).poll_next(cx) {
Poll::Ready(Ok(Some(t))) => t, Poll::Ready(Some(Ok(t))) => t,
Poll::Ready(Ok(None)) => { Poll::Ready(Some(Err(e))) => {
warn!("Server Connectioned errored");
session.shutdown();
return Poll::Ready(Err(Box::new(e)));
}
Poll::Ready(None) => {
warn!("Connection to server closed."); warn!("Connection to server closed.");
session.shutdown(); session.shutdown();
return Ok(Poll::Ready(())); return Poll::Ready(Ok(()));
} }
Poll::Pending => return Poll::Pending, Poll::Pending => return Poll::Pending,
Poll::Ready(Err(e)) => {
session.shutdown();
return Err(From::from(e));
}
}; };
session.dispatch(cmd, data); session.dispatch(cmd, data);
} }
} }
@ -352,7 +342,7 @@ where
impl<S> Drop for DispatchTask<S> impl<S> Drop for DispatchTask<S>
where where
S: Stream<Item = Result<((u8, Bytes), ())>>, S: Stream<Item = io::Result<(u8, Bytes)>> + Unpin,
{ {
fn drop(&mut self) { fn drop(&mut self) {
debug!("drop Dispatch"); debug!("drop Dispatch");