1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
use crate::{handle_packet, CLIENT_ID_COUNTER};
use karlcommon::{socket_path, version, ClientboundPacket, ProtoError, ServerboundPacket};
use log::{debug, error, info, warn};
use std::io;
use std::io::{BufRead, BufReader, ErrorKind, Write};
use std::os::unix::net::{UnixListener, UnixStream};
use std::thread;
pub fn run() {
if socket_path().exists() {
info!("remove old socket");
std::fs::remove_file(socket_path()).unwrap();
}
let listener = UnixListener::bind(socket_path()).unwrap();
info!("listening.");
loop {
let (stream, addr) = listener.accept().unwrap();
let id = CLIENT_ID_COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
thread::spawn(move || {
info!("client connected: {:?}", addr);
if let Err(err) = handle_connection(id, stream) {
warn!("client dropped: {:?} ({})", addr, err);
} else {
info!("client dropped: {:?}", addr);
}
});
}
}
fn handle_connection(id: u32, mut stream: UnixStream) -> io::Result<()> {
let mut reader = BufReader::new(stream.try_clone()?);
let (responder, responses) = crossbeam_channel::unbounded();
responder
.send(ClientboundPacket::Handshake {
version: version!(),
})
.unwrap();
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:?}");
handle_packet(id, packet, responder.clone());
}
Err(err) => {
warn!("client error: {:?}", &err);
responder
.send(ClientboundPacket::Error(ProtoError::FormatError(format!(
"{}",
&err
))))
.map_err(|_| io::Error::from(ErrorKind::InvalidInput))?
}
}
buf.clear();
}
}
}
|