work
This commit is contained in:
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
});
|
||||
});
|
||||
|
||||
(
|
||||
|
||||
@@ -4,6 +4,7 @@ mod no_cert;
|
||||
mod transfer;
|
||||
|
||||
pub use no_cert::*;
|
||||
use rand::{TryRngCore, rngs::OsRng};
|
||||
pub use transfer::*;
|
||||
|
||||
pub const SERVER_NAME: &str = "openworm";
|
||||
@@ -13,8 +14,15 @@ pub const BINCODE_CONFIG: Configuration = bincode::config::standard();
|
||||
pub enum ClientMsg {
|
||||
SendMsg(NetClientMsg),
|
||||
RequestMsgs,
|
||||
CreateAccount { username: String, password: String },
|
||||
Login { username: String, password: String },
|
||||
CreateAccount {
|
||||
username: String,
|
||||
password: String,
|
||||
device: LoginKey,
|
||||
},
|
||||
Login {
|
||||
username: String,
|
||||
password: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, bincode::Encode, bincode::Decode)]
|
||||
@@ -63,3 +71,26 @@ pub fn install_crypto_provider() {
|
||||
.install_default()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[derive(Debug, bincode::Encode, bincode::Decode)]
|
||||
pub struct LoginKey([u8; LoginKey::BYTE_LEN]);
|
||||
impl LoginKey {
|
||||
pub const BIT_LEN: usize = 1024;
|
||||
pub const BYTE_LEN: usize = Self::BIT_LEN / 8;
|
||||
|
||||
pub fn new() -> Self {
|
||||
let mut key = [0u8; Self::BYTE_LEN];
|
||||
OsRng
|
||||
.try_fill_bytes(&mut key)
|
||||
.expect("failed to generate random key");
|
||||
Self(key)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Vec<u8>> for LoginKey {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
|
||||
Ok(Self(value.try_into().map_err(|_| ())?))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ use std::{
|
||||
};
|
||||
|
||||
use directories_next::ProjectDirs;
|
||||
use ed25519_dalek::VerifyingKey;
|
||||
|
||||
use crate::net::BINCODE_CONFIG;
|
||||
|
||||
@@ -47,3 +48,5 @@ impl DataDir {
|
||||
bincode::encode_into_std_write(data, &mut file, BINCODE_CONFIG).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DevicePublicKey(VerifyingKey);
|
||||
|
||||
Reference in New Issue
Block a user