aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <yvchraiqi@protonmail.com>2022-06-06 22:48:55 +0200
committermetamuffin <yvchraiqi@protonmail.com>2022-06-06 22:48:55 +0200
commitbce701919dad8fb3ce0e06ada4d4892240d483e2 (patch)
tree8650bb6076b851dc828b4ae10472893512c06330
parentdf31b14b3736a1e71dd8c08297f84e3fba228e39 (diff)
downloadkarlender-bce701919dad8fb3ce0e06ada4d4892240d483e2.tar
karlender-bce701919dad8fb3ce0e06ada4d4892240d483e2.tar.bz2
karlender-bce701919dad8fb3ce0e06ada4d4892240d483e2.tar.zst
a
-rw-r--r--Cargo.lock51
-rw-r--r--Cargo.toml2
-rw-r--r--protocol.d.ts13
-rw-r--r--src/interface.rs68
-rw-r--r--src/lib.rs3
-rw-r--r--src/main.rs35
-rw-r--r--src/protocol.rs4
7 files changed, 148 insertions, 28 deletions
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]]
@@ -45,6 +47,26 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -73,6 +95,18 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -129,6 +163,12 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -149,6 +189,17 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
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<ClientboundPacket>)>) {
+ 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<ClientboundPacket>)>,
+) -> 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::<ServerboundPacket>(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<ClientboundPacket>)>) {
+ 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<Task>),
}
#[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<Condition>,
deadline: Option<Condition>,
}
-