summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorache <ache@ache.one>2024-11-15 04:05:33 +0100
committerache <ache@ache.one>2024-11-15 04:05:33 +0100
commit3116eaa74b45c21ee925e0c9e39ac58303ef58e0 (patch)
treeb029aee811e285620b88e15a980fa2938a2726ed
Init commit
-rw-r--r--Cargo.toml22
-rw-r--r--screen-rfp.pngbin0 -> 81160 bytes
-rw-r--r--src/main.rs129
3 files changed, 151 insertions, 0 deletions
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..f56955b
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,22 @@
+[package]
+name = "vncstrost"
+version = "0.1.0"
+description = "Simple trolling VNC server"
+authors = ["ache <ache@ache.one>"]
+license = "MPL-2.0"
+edition = "2021"
+
+[dependencies]
+ascii = { version = "1.1", default-features = false }
+async-trait = "0.1.80"
+bitflags = "2.4"
+env_logger = "0.11"
+futures = "0.3.30"
+log = "0.4.17"
+thiserror = "1.0"
+tokio = { version = "1", features = ["full"] }
+anyhow = "1.0"
+clap = { version = "4.5", features = ["derive"] }
+image = "0.25.1"
+rfb = { path = 'deps/rfb' }
+
diff --git a/screen-rfp.png b/screen-rfp.png
new file mode 100644
index 0000000..a279a96
--- /dev/null
+++ b/screen-rfp.png
Binary files differ
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..96455ac
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,129 @@
+use anyhow::Result;
+use async_trait::async_trait;
+// use clap::{Parser, ValueEnum};
+use env_logger;
+use image::GenericImageView;
+use image::ImageReader;
+use log::info;
+use rfb::encodings;
+use rfb::pixel_formats::rgb_888;
+use rfb::rfb::{
+ FramebufferUpdate, KeyEvent, PixelFormat, ProtoVersion, Rectangle, SecurityType, SecurityTypes,
+};
+use rfb::server::{Server, VncServer, VncServerConfig, VncServerData};
+use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+
+const WIDTH: usize = 1053;
+const HEIGHT: usize = 1053;
+
+#[derive(Clone)]
+struct AcheServer {
+ rgb_order: (u8, u8, u8),
+ big_endian: bool,
+}
+
+#[tokio::main]
+async fn main() -> Result<()> {
+ env_logger::init();
+ /*
+ TODO: Should add a CLI option to configure the port to listen to.
+
+ TODO: Should add a CLI option to configure the image to display.
+ */
+
+ let pf = PixelFormat::new_colorformat(
+ rgb_888::BITS_PER_PIXEL,
+ rgb_888::DEPTH,
+ false, // endianness = little-endian
+ order_to_shift(0),
+ rgb_888::MAX_VALUE,
+ order_to_shift(1),
+ rgb_888::MAX_VALUE,
+ order_to_shift(2),
+ rgb_888::MAX_VALUE,
+ );
+ info!("Starting server: pixel format; {:#?}", pf);
+
+ let config = VncServerConfig {
+ addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 5901),
+ version: ProtoVersion::Rfb38,
+ sec_types: SecurityTypes(vec![SecurityType::None, SecurityType::VncAuthentication]),
+ name: "rfb-ache-server".to_string(),
+ };
+ let data = VncServerData {
+ width: WIDTH as u16,
+ height: HEIGHT as u16,
+ input_pixel_format: pf.clone(),
+ };
+ let server = AcheServer {
+ rgb_order: (0, 1, 2),
+ big_endian: false,
+ };
+ let s = VncServer::new(server, config, data);
+ s.start().await?;
+
+ Ok(())
+}
+
+fn order_to_shift(order: u8) -> u8 {
+ assert!(order <= 3);
+ (3 - order) * rgb_888::BITS_PER_COLOR
+}
+
+fn order_to_index(order: u8, big_endian: bool) -> u8 {
+ assert!(order <= 3);
+
+ if big_endian {
+ order
+ } else {
+ 4 - order - 1
+ }
+}
+
+fn generate_image(name: &str, big_endian: bool, rgb_order: (u8, u8, u8)) -> Vec<u8> {
+ const LEN: usize = WIDTH * HEIGHT * rgb_888::BYTES_PER_PIXEL;
+ let mut pixels = vec![0xffu8; LEN];
+
+ let img = ImageReader::open(name).unwrap().decode().unwrap();
+
+ let (r, g, b) = rgb_order;
+ let r_idx = order_to_index(r, big_endian) as usize;
+ let g_idx = order_to_index(g, big_endian) as usize;
+ let b_idx = order_to_index(b, big_endian) as usize;
+ let x_idx = rgb_888::unused_index(r_idx, g_idx, b_idx);
+
+ // Convert the input image pixels to the requested pixel format.
+ for (x, y, pixel) in img.pixels() {
+ let ux = x as usize;
+ let uy = y as usize;
+
+ let y_offset = WIDTH * rgb_888::BYTES_PER_PIXEL;
+ let x_offset = ux * rgb_888::BYTES_PER_PIXEL;
+
+ pixels[uy * y_offset + x_offset + r_idx] = pixel[0];
+ pixels[uy * y_offset + x_offset + g_idx] = pixel[1];
+ pixels[uy * y_offset + x_offset + b_idx] = pixel[2];
+ pixels[uy * y_offset + x_offset + x_idx] = pixel[3];
+ }
+
+ pixels
+}
+
+#[async_trait]
+impl Server for AcheServer {
+ async fn get_framebuffer_update(&self) -> FramebufferUpdate {
+ let pixels_width = 1053;
+ let pixels_height = 1053;
+ let pixels = generate_image("screen-rfp.png", self.big_endian, self.rgb_order);
+ let r = Rectangle::new(
+ 0,
+ 0,
+ pixels_width,
+ pixels_height,
+ Box::new(encodings::RawEncoding::new(pixels)),
+ );
+ FramebufferUpdate::new(vec![r])
+ }
+
+ async fn key_event(&self, _ke: KeyEvent) {}
+}