From 4b8cd6f6d4a1488e2fa2e3743ad07f057713d8f1 Mon Sep 17 00:00:00 2001 From: 2ndbeam <2ndbeam@disroot.org> Date: Tue, 18 Nov 2025 17:49:45 +0300 Subject: [PATCH] init --- .gitignore | 1 + Cargo.lock | 7 +++ Cargo.toml | 6 +++ src/main.rs | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 138 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..bb5e910 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "socket_test" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..31d56d7 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "socket_test" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..22635aa --- /dev/null +++ b/src/main.rs @@ -0,0 +1,124 @@ +use std::{io::{Read, Write}, os::unix::net::{UnixListener, UnixStream}, thread}; + +fn stream_shutdown(stream: &UnixStream, state: &mut ConnectionState) { + if let Err(err) = stream.shutdown(std::net::Shutdown::Both) { + eprintln!("Stream shutdown error: {err}"); + } else { + println!("Closed connection..."); + } + *state = ConnectionState::Shutdown; +} + +fn stream_write(stream: &mut UnixStream, bytes: &[u8], state: &mut ConnectionState) { + if let Err(err) = stream.write_all(bytes) { + eprintln!("Stream writing error: {err}"); + stream_shutdown(stream, state); + } +} + +fn stream_read<'a>(stream: &'a mut UnixStream, buf: &'a mut [u8], state: &mut ConnectionState) -> String { + if let Err(err) = stream.read(buf) { + eprintln!("Stream reading error: {err}"); + stream_shutdown(stream, state); + } + + match str::from_utf8(&buf) { + Ok(str) => str.to_owned(), + Err(_) => String::new() + } +} + +enum ConnectionState { + Initialized, + Identified(String), + Shutdown, +} + +fn handle_client(mut stream: UnixStream) { + let mut buf: [u8; 64]; + let mut state = ConnectionState::Initialized; + let mut cnt = 0usize; + stream_write(&mut stream, b"ID THYSELF\n", &mut state); + + loop { + buf = [0; 64]; + let string = stream_read(&mut stream, &mut buf, &mut state).to_owned(); + + if string.is_empty() { + continue; + } + + println!("recv: {string}"); + + if string.starts_with("END") { + stream_write(&mut stream, b"CON CLOSED\n", &mut state); + stream_shutdown(&stream, &mut state); + break; + } + + + match &state { + ConnectionState::Initialized => { + state = ConnectionState::Identified(string.to_owned()); + stream_write(&mut stream, b"WELCOME\n", &mut state); + } + ConnectionState::Identified(name) => { + if string.starts_with("HI") { + stream_write(&mut stream, format!("HELLO {}\n", name).as_bytes() , &mut state); + continue; + } + + if string.starts_with("SET ") { + let splitstr = string.split(' ').nth(1); + if let Some(numstr) = splitstr { + println!("{}", numstr); + match numstr.parse::() { + Ok(num) => { + cnt = num; + stream_write(&mut stream, b"SET OK\n", &mut state); + } + Err(_) => { + stream_write(&mut stream, b"INCOR USIZE\n", &mut state); + } + } + } else { + stream_write(&mut stream, b"NOT ENOUGH ARGS\n", &mut state); + } + continue; + } + + if string.starts_with("ECHO") { + stream_write(&mut stream, format!("CNT={cnt}\n").as_bytes(), &mut state); + continue; + } + + if string.starts_with("HELP") { + stream_write(&mut stream, b"AVAIL: ECHO; END; HELP; HI; SET N\n", &mut state); + continue; + } + + stream_write(&mut stream, b"UNDEF; TRY HELP\n", &mut state); + } + ConnectionState::Shutdown => break + } + } +} + +fn main() -> std::io::Result<()> { + let listener = UnixListener::bind("/tmp/rustsock")?; + + for stream in listener.incoming() { + match stream { + Ok(stream) => { + println!("Received connection..."); + thread::spawn(|| handle_client(stream)); + } + Err(err) => { + eprintln!("Connection failed: {err}"); + break; + } + } + } + + Ok(()) +}