plankircd/src/main.rs

160 lines
6.9 KiB
Rust
Raw Normal View History

2018-06-18 16:46:09 +02:00
extern crate tokio;
2018-06-19 16:45:28 +02:00
extern crate futures;
2018-06-18 16:46:09 +02:00
2018-06-20 16:38:12 +02:00
//use futures::prelude::*;
use futures::sync::mpsc::UnboundedSender;
use std::net::SocketAddr;
2018-06-18 16:46:09 +02:00
use tokio::prelude::*;
2018-06-19 16:45:28 +02:00
use tokio::io;
use std::iter;
use std::collections::HashMap;
use std::io::BufReader;
2018-06-18 16:46:09 +02:00
use tokio::net::TcpListener;
2018-06-19 16:45:28 +02:00
use std::sync::{Arc, Mutex};
2018-06-18 16:46:09 +02:00
2018-06-18 16:24:39 +02:00
pub mod models;
2018-06-19 16:45:28 +02:00
pub mod user;
2018-06-20 16:38:12 +02:00
pub mod channel;
pub mod context;
use context::Context;
2018-06-18 16:24:39 +02:00
fn main() {
2018-06-18 16:46:09 +02:00
let addr = "127.0.0.1:6667".parse().unwrap();
let listener = TcpListener::bind(&addr)
.expect("unable to bind TCP listener");
2018-06-20 16:38:12 +02:00
let mut context = Context::new();
2018-06-19 16:45:28 +02:00
2018-06-18 16:46:09 +02:00
let server = listener.incoming()
.map_err(|e| eprintln!("accept failed = {:?}", e))
2018-06-20 16:38:12 +02:00
.for_each(move |sock| {
2018-06-19 16:45:28 +02:00
let addr = sock.peer_addr().unwrap();
println!("{} connected", addr);
2018-06-18 16:46:09 +02:00
let (reader, writer) = sock.split();
2018-06-20 16:38:12 +02:00
let (tx, rx) = futures::sync::mpsc::unbounded();
2018-06-18 16:46:09 +02:00
2018-06-21 16:33:13 +02:00
context.connect(addr, tx);
2018-06-18 16:46:09 +02:00
2018-06-20 16:38:12 +02:00
let context_inner = context.clone();
2018-06-19 16:45:28 +02:00
2018-06-20 16:38:12 +02:00
let reader = BufReader::new(reader);
2018-06-19 16:45:28 +02:00
let iter = stream::iter_ok::<_, io::Error>(iter::repeat(()));
2018-06-20 16:38:12 +02:00
let socket_reader = iter.fold(reader, move |reader, _| {
let mut context = context_inner.clone();
2018-06-19 16:45:28 +02:00
io::read_until(reader, b'\n', vec![])
.and_then(|(reader, vec)| {
if vec.len() == 0 {
Err(io::Error::new(io::ErrorKind::BrokenPipe, "broken pipe"))
}
else {
Ok((reader, vec))
}
})
2018-06-20 16:38:12 +02:00
.map(|(reader, vec)| {
match String::from_utf8(vec) {
Ok(s) => (reader, s),
Err(e) => {
eprintln!("failed converting data: {:?}", e);
(reader, "ERROR".to_string())
},
}
})
.map(move |(reader, line)| {
use models::IrcMessage;
2018-06-21 16:33:13 +02:00
for l in line.lines() {
println!("{} -> {}", addr, l.trim());
}
let res = IrcMessage::from_str(&line);
if let Err(e) = res {
eprintln!("error parsing command: {:?}", e);
return reader;
}
let msg = res.unwrap();
use models::IrcCommand::*;
match msg.command {
NICK => {
if msg.params.len() < 1 {
context.send_message_to(&addr, IrcMessage::new(Some("plankircd"), Num(431), vec!["*", "No nickname given"]));
}
else {
let nick = &msg.params[0];
if context.nick_exists(nick) {
context.send_message_to(&addr, IrcMessage::new(Some("plankircd"), Num(443), vec!["*", nick, "Nickname is already in use"]));
}
else {
let (valid, old) = {
let mut lock = context.users.lock().unwrap();
let mut user = lock.get_mut(&addr).unwrap();
let old = user.nickname.clone();
user.set_nick(nick);
(user.is_valid(), old)
};
if valid {
if !context.is_registered(&addr) {
context.register_user(&addr);
2018-06-20 16:38:12 +02:00
}
2018-06-21 16:33:13 +02:00
else {
context.send_message_to(&addr, IrcMessage::new(Some(&old), NICK, vec![nick]));
2018-06-20 16:38:12 +02:00
}
}
2018-06-21 16:33:13 +02:00
}
2018-06-20 16:38:12 +02:00
}
2018-06-19 16:45:28 +02:00
},
2018-06-21 16:33:13 +02:00
USER => {
if msg.params.len() < 4 {
}
else {
let valid = {
let mut lock = context.users.lock().unwrap();
let mut user = lock.get_mut(&addr).unwrap();
user.set_user(&msg.params[0], &msg.params[2], &msg.params[3]);
user.is_valid()
};
if valid && !context.is_registered(&addr) {
context.register_user(&addr);
}
}
},
PING => {context.send_message_to(&addr, IrcMessage::new(Some("plankircd"), PONG, vec!["plankircd", &msg.params[0]]));},
PRIVMSG => {
if msg.params[0].starts_with('#') {
}
else {
let users = context.users.lock().unwrap();
let from = &users[&addr];
if let Some(user) = users.values().find(|u| u.nickname == msg.params[0]) {
user.privmsg(from, &msg.params[1]);
}
}
}
QUIT => context.disconnect(&addr),
_ => println!("Unhandled command: {}", msg.command),
2018-06-20 16:38:12 +02:00
}
2018-06-19 16:45:28 +02:00
reader
})
2018-06-20 16:38:12 +02:00
})
.map_err(|_|());
let socket_writer = rx.fold(writer, move |writer, msg| {
2018-06-21 16:33:13 +02:00
for l in msg.lines() {
println!("{} <- {}", addr, l.trim());
}
2018-06-20 16:38:12 +02:00
io::write_all(writer, msg.into_bytes())
.map(|(writer, _)| writer)
.map_err(|_| ())
2018-06-18 16:46:09 +02:00
});
2018-06-20 16:38:12 +02:00
let connection = socket_reader.map(|_|()).select(socket_writer.map(|_|()));
2018-06-19 16:45:28 +02:00
2018-06-18 16:46:09 +02:00
// Spawn the future as a concurrent task.
2018-06-20 16:38:12 +02:00
tokio::spawn(connection.then(move |_| {
2018-06-19 16:45:28 +02:00
println!("Connection {} closed", addr);
Ok(())
}))
2018-06-18 16:46:09 +02:00
});
tokio::run(server);
2018-06-18 16:24:39 +02:00
}