From bce701919dad8fb3ce0e06ada4d4892240d483e2 Mon Sep 17 00:00:00 2001 From: metamuffin Date: Mon, 6 Jun 2022 22:48:55 +0200 Subject: a --- Cargo.lock | 51 ++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 ++ protocol.d.ts | 13 ++++++----- src/interface.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 ++- src/main.rs | 35 +++++++++++++---------------- src/protocol.rs | 4 +++- 7 files changed, 148 insertions(+), 28 deletions(-) create mode 100644 src/interface.rs diff --git a/Cargo.lock b/Cargo.lock index a13bf2e..e7a6415 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,9 +33,11 @@ name = "calender-thing" version = "0.1.0" dependencies = [ "anyhow", + "crossbeam-channel", "env_logger", "log", "serde", + "serde_json", ] [[package]] @@ -44,6 +46,26 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "crossbeam-channel" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +dependencies = [ + "cfg-if", + "lazy_static", +] + [[package]] name = "env_logger" version = "0.9.0" @@ -72,6 +94,18 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "itoa" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.126" @@ -128,6 +162,12 @@ version = "0.6.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" +[[package]] +name = "ryu" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" + [[package]] name = "serde" version = "1.0.137" @@ -148,6 +188,17 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "syn" version = "1.0.96" diff --git a/Cargo.toml b/Cargo.toml index 03ed20d..45bcda5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,6 @@ serde = { version = "1.0.137", features = ["derive"] } anyhow = "1.0.57" log = "0.4.17" env_logger = "0.9.0" +crossbeam-channel = "0.5.4" +serde_json = "1.0.81" diff --git a/protocol.d.ts b/protocol.d.ts index f119045..36bf3e1 100644 --- a/protocol.d.ts +++ b/protocol.d.ts @@ -1,27 +1,28 @@ // { type: "handshake", version: "10"} // { type: "handshake", data: {version: "10"}} -// { "handshake": {version: "10"}} +//! { "handshake": {version: "10"}} -export type ServerboundPacket = null -export type ClientboundPacket = Handshake +export type ServerboundPacket = Download +export type ClientboundPacket = Handshake | DownloadResponse interface Handshake { type: "handshake" - version: string + data: { version: string } } interface Download { type: "download", + data: null } interface DownloadResponse { type: "download_response", - entries: TodoEntry[] + data: { tasks: Task[] } } -interface TodoEntry { +interface Task { name: string, description: string, diff --git a/src/interface.rs b/src/interface.rs new file mode 100644 index 0000000..568c450 --- /dev/null +++ b/src/interface.rs @@ -0,0 +1,68 @@ +use std::io; +use std::io::{BufRead, BufReader, ErrorKind, Write}; +use std::os::unix::net::{UnixListener, UnixStream}; +use std::thread; + +use super::protocol::{ClientboundPacket, ServerboundPacket}; +use crossbeam_channel::Sender; +use log::{debug, error, info, warn}; + +pub fn network_loop(s: Sender<(u32, ServerboundPacket, Sender)>) { + let listener = UnixListener::bind("/run/user/1000/calendar").unwrap(); + let mut id_counter = 0; + + loop { + let (stream, addr) = listener.accept().unwrap(); + let s = s.clone(); + let id = id_counter; + id_counter += 1; + thread::spawn(move || { + info!("client connected: {:?}", addr); + if let Err(err) = handle_connection(id, stream.try_clone().unwrap(), s.clone()) { + warn!("client dropped: {:?} ({})", addr, err); + } else { + info!("client dropped: {:?}", addr); + } + }); + } +} + +fn handle_connection( + id: u32, + mut stream: UnixStream, + s: Sender<(u32, ServerboundPacket, Sender)>, +) -> io::Result<()> { + let mut reader = BufReader::new(stream.try_clone()?); + let (responder, responses) = crossbeam_channel::unbounded(); + thread::spawn(move || { + for m in responses { + debug!("{id} -> {m:?}"); + match stream + .write_fmt(format_args!("{}\n", serde_json::to_string(&m).unwrap())) + .map_err(|e| e.kind()) + { + Ok(_) => (), + Err(ErrorKind::BrokenPipe) => break, + Err(e) => error!("network error: {:?}", e), + } + } + }); + let mut buf = String::new(); + loop { + if reader.read_line(&mut buf)? == 0 { + break Ok(()); + }; + match serde_json::from_str::(buf.as_str()) { + Ok(packet) => { + debug!("{id} <- {packet:?}"); + s.send((id, packet, responder.clone())) + .map_err(|_| io::Error::from(ErrorKind::InvalidInput))?; + } + Err(err) => responder + .send(ClientboundPacket::Error(format!("{}", &err))) + .map_err(|_| io::Error::from(ErrorKind::InvalidInput))?, + } + + buf.clear(); + } +} diff --git a/src/lib.rs b/src/lib.rs index 0d96cad..c5d7a22 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,3 @@ pub mod protocol; -pub mod occurence; \ No newline at end of file +pub mod occurence; +pub mod interface; diff --git a/src/main.rs b/src/main.rs index a26a1dd..fb975d6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,27 +1,22 @@ +use std::time::Duration; -use std::io::{BufRead, BufReader}; -use std::os::unix::net::{UnixListener, UnixStream}; -use std::thread; - -fn handle_client(stream: UnixStream) { - let stream = BufReader::new(stream); - for line in stream.lines() { - println!("{}", line.unwrap()); - } -} +use calender_thing::{ + interface::network_loop, + protocol::{ClientboundPacket, ServerboundPacket}, +}; +use crossbeam_channel::{Receiver, Sender}; fn main() { - let listener = UnixListener::bind("/run/user/1000/calendar").unwrap(); + let (s, r) = crossbeam_channel::unbounded(); + std::thread::spawn(move || network_loop(s)); + main_loop(r) +} - for stream in listener.incoming() { - match stream { - Ok(stream) => { - thread::spawn(|| handle_client(stream)); - } - Err(err) => { - println!("Error: {}", err); - break; - } +fn main_loop(packets: Receiver<(u32, ServerboundPacket, Sender)>) { + loop { + for (client_id, packet, responder) in packets.try_iter() { + println!("{:?}, {:?}, {:?}", client_id, packet, responder); } + std::thread::sleep(Duration::from_secs_f64(10.0 / 30.0)); } } diff --git a/src/protocol.rs b/src/protocol.rs index fdd84d4..a09f879 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -3,12 +3,15 @@ use serde::{Deserialize, Serialize}; use crate::occurence::Condition; #[derive(Debug, Serialize, Deserialize)] +#[serde(tag = "type", content = "data", rename_all = "snake_case")] pub enum ClientboundPacket { Handshake { version: String }, + Error(String), DownloadResponse(Vec), } #[derive(Debug, Serialize, Deserialize)] +#[serde(tag = "type", content = "data", rename_all = "snake_case")] pub enum ServerboundPacket { Download, } @@ -27,4 +30,3 @@ pub struct Task { occurence: Option, deadline: Option, } - -- cgit v1.2.3-70-g09d2