This commit is contained in:
Alexey 2025-11-18 17:49:45 +03:00
commit 4b8cd6f6d4
4 changed files with 138 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

7
Cargo.lock generated Normal file
View file

@ -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"

6
Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[package]
name = "socket_test"
version = "0.1.0"
edition = "2024"
[dependencies]

124
src/main.rs Normal file
View file

@ -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::<usize>() {
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(())
}