This commit is contained in:
2026-01-22 23:33:14 -05:00
parent ace356381a
commit bcbd6cb6c8
8 changed files with 180 additions and 77 deletions

View File

@@ -1,4 +1,9 @@
use openworm::rsc::{DataDir, DataRsc};
use ed25519_dalek::SigningKey;
use openworm::{
net::LoginKey,
rsc::{DataDir, DataRsc},
};
use rand::{TryRngCore, rngs::OsRng};
pub struct ClientData {
pub dir: DataDir,
@@ -18,7 +23,15 @@ impl ClientData {
self.dir.save(&self.cache);
}
pub fn device_key(&self) -> {
pub fn login_key(&self, user: &str) -> LoginKey {
let entry = keyring::Entry::new("openworm", user).expect("failed to open keyring entry");
if let Ok(secret) = entry.get_secret() {
secret
.try_into()
.expect("failed to load key from secrets (invalid format)")
} else {
LoginKey::new()
}
}
}

View File

@@ -2,8 +2,7 @@
use crate::{
data::ClientData,
net::{NetHandle, NetSender},
state::{ClientState, LoggedIn, Login},
state::{ClientState, LoggedIn},
};
use iris::prelude::*;
use openworm::net::{ClientMsg, ServerMsg, install_crypto_provider};
@@ -37,7 +36,6 @@ pub struct Client {
pub type Rsc = DefaultRsc<Client>;
pub enum ClientEvent {
Connect { send: NetSender },
ServerMsg(ServerMsg),
Err(String),
}
@@ -85,19 +83,6 @@ impl DefaultAppState for Client {
_render: &mut UiRenderState,
) {
match event {
ClientEvent::Connect { send } => {
let ClientState::Connect(connect) = self.state.take() else {
panic!("invalid state");
};
let th = connect.handle.unwrap();
self.state = ClientState::Login(Login {
handle: NetHandle {
send: send.clone(),
thread: th,
},
});
// login_screen(self, ui).set_ptr(&self.main_ui, ui);
}
ClientEvent::ServerMsg(msg) => match msg {
ServerMsg::SendMsg(msg) => {
if let ClientState::LoggedIn(state) = &mut self.state

View File

@@ -9,53 +9,37 @@ use quinn::{
use std::{
net::{Ipv6Addr, SocketAddr, SocketAddrV6, ToSocketAddrs},
sync::Arc,
thread::JoinHandle,
time::Duration,
};
use tokio::sync::mpsc::UnboundedSender;
use winit::{event_loop::EventLoopProxy, window::Window};
use tokio::sync::{mpsc::UnboundedSender, oneshot::Receiver};
use winit::event_loop::EventLoopProxy;
pub const CLIENT_SOCKET: SocketAddr =
SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, 0, 0, 0));
pub struct ConnectInfo {
pub ip: String,
pub url: String,
}
pub struct NetHandle {
pub send: NetSender,
pub thread: JoinHandle<()>,
send: UnboundedSender<NetCtrlMsg>,
}
#[derive(Clone)]
pub struct AppHandle {
pub proxy: EventLoopProxy<ClientEvent>,
pub window: Arc<Window>,
}
impl AppHandle {
pub fn send(&self, event: ClientEvent) {
self.proxy.send_event(event).unwrap_or_else(|_| panic!());
self.window.request_redraw();
}
}
pub fn connect(handle: AppHandle, info: ConnectInfo) -> JoinHandle<()> {
std::thread::spawn(move || {
if let Err(msg) = connect_the(handle.clone(), info) {
handle.send(ClientEvent::Err(msg));
}
})
}
type NetResult<T> = Result<T, String>;
#[derive(Clone)]
pub struct NetSender {
send: UnboundedSender<NetCtrlMsg>,
}
pub enum NetCtrlMsg {
Exchange(ClientMsg, Receiver<>),
Send(ClientMsg),
Exit,
}
@@ -66,12 +50,6 @@ impl From<ClientMsg> for NetCtrlMsg {
}
}
impl NetSender {
pub fn send(&self, msg: impl Into<NetCtrlMsg>) {
let _ = self.send.send(msg.into());
}
}
impl NetHandle {
pub fn send(&self, msg: impl Into<NetCtrlMsg>) {
self.send.send(msg.into());
@@ -79,7 +57,6 @@ impl NetHandle {
pub fn exit(self) {
self.send(NetCtrlMsg::Exit);
let _ = self.thread.join();
}
}
@@ -140,12 +117,11 @@ async fn connection_no_cert(addr: SocketAddr) -> NetResult<(Endpoint, Connection
Ok((endpoint, con))
}
#[tokio::main]
async fn connect_the(handle: AppHandle, info: ConnectInfo) -> NetResult<()> {
pub async fn connect(msg: impl MsgHandler, info: ConnectInfo) -> Result<NetHandle, String> {
let (send, mut ui_recv) = tokio::sync::mpsc::unbounded_channel::<NetCtrlMsg>();
let addr = info
.ip
.url
.to_socket_addrs()
.map_err(|e| e.to_string())?
.next()
@@ -153,38 +129,44 @@ async fn connect_the(handle: AppHandle, info: ConnectInfo) -> NetResult<()> {
let (endpoint, conn) = connection_no_cert(addr).await?;
let conn_ = conn.clone();
handle.send(ClientEvent::Connect {
send: NetSender { send },
});
let recv = ServerRecv { handle };
let recv = ServerRecv { msg };
tokio::spawn(recv_uni(conn_, recv.into()));
while let Some(msg) = ui_recv.recv().await {
match msg {
NetCtrlMsg::Send(msg) => {
if send_uni(&conn, msg).await.is_err() {
println!("disconnected from server");
tokio::spawn(async move {
while let Some(msg) = ui_recv.recv().await {
match msg {
NetCtrlMsg::Send(msg) => {
if send_uni(&conn, msg).await.is_err() {
println!("disconnected from server");
break;
}
}
NetCtrlMsg::Exit => {
conn.close(0u32.into(), &[]);
endpoint.wait_idle().await;
break;
}
}
NetCtrlMsg::Exit => {
conn.close(0u32.into(), &[]);
endpoint.wait_idle().await;
break;
}
}
});
Ok(NetHandle { send })
}
pub trait MsgHandler: Sync + Send + 'static {
fn run(&self, msg: ServerMsg) -> impl Future<Output = ()> + Send;
}
impl<F: AsyncFn(ServerMsg) + Sync + Send + 'static> MsgHandler for F {
async fn run(&self, msg: ServerMsg) {
self(msg);
}
Ok(())
}
struct ServerRecv {
handle: AppHandle,
struct ServerRecv<F: MsgHandler> {
msg: F,
}
impl RecvHandler<ServerMsg> for ServerRecv {
impl<F: MsgHandler> RecvHandler<ServerMsg> for ServerRecv<F> {
async fn msg(&self, msg: ServerMsg) {
self.handle.send(ClientEvent::ServerMsg(msg));
self.msg.run(msg).await;
}
}

View File

@@ -1,3 +1,5 @@
use crate::net::{self, ConnectInfo};
use super::*;
pub fn start(rsc: &mut Rsc) -> WeakWidget {
@@ -41,7 +43,20 @@ pub fn create_account(rsc: &mut Rsc) -> WeakWidget {
let create = Button::submit("create", rsc);
rsc.events.register(create, Submit, move |ctx, rsc| {
ctx.state.data
let url = rsc[url].content();
let user = rsc[username].content();
let pwd = rsc[password].content();
let key = ctx.state.data.login_key(&user);
rsc.spawn_task(async |ctx| {
let net = net::connect(
async |msg| {
println!("msg recv :joy:");
},
ConnectInfo { url },
)
.await
.expect("failed to connect");
});
});
(