+ Websocket setup is almost proper but it completely hangs after we start listening for connections

Of course this is an issue because we can no longer get data from the user
A full rearchitecting may be in order here however its not impossible to modify the current architecture so far

The main issue here is that the cache is doing too much I think

If the termion(main input) task does its thing, and a socket task,
waits around waiting to build a sub task(socket) then we may be able to
pass messages to the socket task to open up sockets when request
This allows us to have shared state via message passing and a main task
can take care of updating the cache.

The renderer can then request data from the cache when it needs to render stuff
This commit is contained in:
shockrah 2021-04-09 22:10:08 -07:00
parent a0b8e82000
commit f92ced1241
3 changed files with 73 additions and 18 deletions

View File

@ -5,7 +5,7 @@ const VOICE_CHANNEL: i32 = 1;
pub const TEXT_CHANNEL: i32 = 2; pub const TEXT_CHANNEL: i32 = 2;
// Network Types // Network Types
#[allow(dead_code)] #[derive(Debug)]
pub struct Message { pub struct Message {
pub id: u64, pub id: u64,
pub time: i64, pub time: i64,
@ -16,6 +16,20 @@ pub struct Message {
pub username: String, pub username: String,
} }
impl Message {
pub fn bogus(s: String) -> Message {
Message {
id: 1,
time: 1,
content: s,
content_type: "text/plain".into(),
channel_id: 1,
userid: 1,
username: "yes".into()
}
}
}
#[derive(Deserialize, Clone)] #[derive(Deserialize, Clone)]
pub struct Channel { pub struct Channel {

View File

@ -12,18 +12,23 @@
* *
*/ */
use crate::api_types::{Channel, Message}; use crate::api_types::Channel;
use crate::net; use crate::net;
use crate::command::Command; use crate::command::Command;
use crate::config::{ConfigFile, ServerConfig}; use crate::config::{ConfigFile, ServerConfig};
use tokio_tungstenite::connect_async;
use futures::StreamExt;
use std::collections::HashMap; use std::collections::HashMap;
use crate::api_types as api;
type ChannelMeta = Channel; type ChannelMeta = Channel;
async fn nop() {
}
struct ChannelCache { struct ChannelCache {
pub meta: ChannelMeta, pub meta: ChannelMeta,
pub messages: Vec<Message> pub messages: Vec<api::Message>
} }
struct ServerCache { struct ServerCache {
@ -37,7 +42,7 @@ pub struct Cache {
// url -> Cache // url -> Cache
servers: HashMap<String, ServerCache>, servers: HashMap<String, ServerCache>,
active_server: Option<ServerConfig>, active_server: Option<ServerConfig>,
active_text: Option<ChannelMeta> active_text: Option<ChannelMeta>,
} }
impl ServerCache { impl ServerCache {
@ -58,18 +63,25 @@ impl Cache {
Cache { Cache {
servers, servers,
active_server: None, active_server: None,
active_text: None active_text: None,
}
} }
} }
impl Cache { pub fn find_serv(&self, portion: String) -> Option<(String, u64)> {
let item = self.servers.iter()
.find(|(url, _)| url.contains(portion.as_str()));
if let Some((url, cache)) = item {
Some((url.clone(), cache.meta.user.id))
} else {
None
}
}
pub async fn switch_channel(&mut self, id: u64) -> Command { pub async fn switch_channel(&mut self, id: u64) -> Command {
if let None = self.active_server { if let None = self.active_server {
return Command::Failure("No active server set!".into()) return Command::Failure("No active server set!".into())
} }
// find the channel meta data
let mut msg = String::new(); let mut msg = String::new();
for (_url, cache) in &self.servers { for (_url, cache) in &self.servers {
if let Some(channel_cache) = cache.channels.get(&id) { if let Some(channel_cache) = cache.channels.get(&id) {
@ -86,22 +98,51 @@ impl Cache {
} }
} }
pub async fn switch_server(&mut self, host: &str) -> Command {
// TODO: implement some better fuzzy finding for better ergonomics fn new_message(&mut self, msg: api::Message, url: String, chan_id: u64) {
// Reallt though the ux is still pretty bad here self.servers.get_mut(&url).unwrap()
// Also it greedily matches so if two servers are behind one domain we're kinda fucked .channels.get_mut(&chan_id).unwrap()
.messages.push(msg);
}
pub async fn setup_websocket(&mut self, url: String, chan_id: u64) {
use crate::log;
// Ignore inactive server state & NoneType<Jwt>
if let None = self.active_server { return; }
match connect_async(url.clone()).await {
Ok((ws, _)) => {
let (_tx, rx) = ws.split();
let reader = rx.for_each(move |message| {
let msg = message.unwrap().into_text().unwrap();
let msg = api::Message::bogus(msg);
log::file(&msg);
self.new_message(msg, url.clone(), chan_id);
nop()
});
//tokio::spawn(reader);
},
Err(e) => {
log::plain(format!("{}: {}\n", e, url))
}
};
}
pub async fn switch_server(&mut self, host: &str) -> (Command, Option<String>) {
// TODO: clean this func to be less ugly/easier to read
let mut found = false; let mut found = false;
let mut err_msg = String::from("Nothing found"); let mut err_msg = String::from("Nothing found");
let mut fresh_token: Option<String> = None;
for (url, meta) in self.servers.iter_mut() { for (url, meta) in self.servers.iter_mut() {
if url.contains(host) { if url.contains(host) {
let id = meta.meta.user.id; let id = meta.meta.user.id;
let secret = &meta.meta.user.secret; let secret = &meta.meta.user.secret;
found = match net::login(url, id, secret).await { found = match net::login(url, id, secret).await {
Ok(jwt) => { Ok(jwt) => {
fresh_token = Some(jwt.clone());
meta.meta.user.jwt = Some(jwt); meta.meta.user.jwt = Some(jwt);
self.active_server = Some(meta.meta.clone()); self.active_server = Some(meta.meta.clone());
// TODO: Setup websocket to server or something idk
net::setup_websocket("adsf").await;
self.active_text = None; self.active_text = None;
true true
}, },
@ -120,9 +161,9 @@ impl Cache {
} }
if found { if found {
Command::Text(format!("logged in - /lc to list to list channels")) (Command::Text(format!("logged in - /lc to list to list channels")), fresh_token)
} else { } else {
Command::Failure(err_msg) (Command::Failure(err_msg), None)
} }
} }

View File

@ -231,7 +231,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
if let Some((url, id)) = app.cache.find_serv(url_portion) { if let Some((url, id)) = app.cache.find_serv(url_portion) {
let (cmd, jwt) = app.cache.switch_server(url.as_str()).await; let (cmd, jwt) = app.cache.switch_server(url.as_str()).await;
let url = net::ws_url(url.as_str(), jwt); let url = net::ws_url(url.as_str(), jwt);
app.cache = app.cache.setup_websocket(url, id).await; app.cache.setup_websocket(url, id).await;
cmd cmd
} else { } else {
Command::Failure("No server found".into()) Command::Failure("No server found".into())