From 4098f06294a2a9c40f4183e9e2ce291550cb69fd Mon Sep 17 00:00:00 2001 From: Zachary Dremann Date: Tue, 3 Jun 2014 18:57:24 -0400 Subject: tmp --- .gitignore | 14 +++ lib.rs | 154 --------------------------------- libirc/lib.rs | 86 +++++++++++++++++++ libirc/libirc-ad3d5237-0.1.rlib | Bin 0 -> 757684 bytes libirc/msg.rs | 185 ++++++++++++++++++++++++++++++++++++++++ main.rs | 31 +++---- 6 files changed, 301 insertions(+), 169 deletions(-) create mode 100644 .gitignore delete mode 100644 lib.rs create mode 100644 libirc/lib.rs create mode 100644 libirc/libirc-ad3d5237-0.1.rlib create mode 100644 libirc/msg.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d87dbe6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +_Store +/src/ +/bin/ +/doc/ +/target/ +/examples/ +/.rust +rusti.sh +.travis.yml +cargo-lite.conf +.symlink-info +*.swp + +Cargo.toml diff --git a/lib.rs b/lib.rs deleted file mode 100644 index a6dfb7b..0000000 --- a/lib.rs +++ /dev/null @@ -1,154 +0,0 @@ -//#![crate_id = "irc#0.1"] -//#![crate_type = "lib"] - -use std::io::net::tcp::TcpStream; -use std::io::IoResult; -use std::io::BufferedReader; -use std::fmt; -use std::from_str::FromStr; - -pub struct IrcConnection { - callbacks: IrcCallbacks, - stream: TcpStream -} - -#[deriving(Clone)] -pub enum Command { - Nick, - User, - Quit, - Join, - Part, - PrivMsg, - Notice, - Motd, - Ping, - Pong, - Error, - Away, - Numeric(u16), - UnknownStr(String) -} - -impl fmt::Show for Command { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "{}", - match *self { - Nick => "NICK".into_maybe_owned(), - User => "USER".into_maybe_owned(), - Quit => "QUIT".into_maybe_owned(), - Join => "JOIN".into_maybe_owned(), - Part => "PART".into_maybe_owned(), - PrivMsg => "PRIVMSG".into_maybe_owned(), - Notice => "NOTICE".into_maybe_owned(), - Motd => "MOTD".into_maybe_owned(), - Ping => "PING".into_maybe_owned(), - Pong => "PONG".into_maybe_owned(), - Error => "ERROR".into_maybe_owned(), - Away => "AWAY".into_maybe_owned(), - Numeric(i) => i.to_str().into_maybe_owned(), - UnknownStr(ref s) => s.as_slice().into_maybe_owned(), - } - ) - } -} - -impl FromStr for Command { - fn from_str(s: &str) -> Option { - Some(match s { - "NICK" => Nick, - "USER" => User, - "QUIT" => Quit, - "JOIN" => Join, - "PART" => Part, - "PRIVMSG" => PrivMsg, - "NOTICE" => Notice, - "MOTD" => Motd, - "PING" => Ping, - "PONG" => Pong, - "ERROR" => Error, - "AWAY" => Away, - other => match from_str::(other) { - Some(i) => Numeric(i), - None => UnknownStr(other.to_string()) - } - }) - } -} - -#[deriving(Clone)] -pub struct Message { - pub prefix: Option, - pub command: Command, - pub arguments: Vec, -} - -impl<'a> fmt::Show for Message { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - if self.prefix.is_some() { - try!(write!(formatter, ":{} ", self.prefix.get_ref())); - } - try!(write!(formatter, "{}", self.command)); - for argument in self.arguments.iter() { - try!(write!(formatter, " {}", *argument)); - } - Ok(()) - } -} - -impl FromStr for Message { - fn from_str(s: &str) -> Option { - //TODO: Parse string - unimplemented!(); - } -} - - - -impl IrcConnection { - pub fn connect( - callbacks: IrcCallbacks, host: &str, port: u16, - nick: &str, username: &str, real_name: &str) -> IoResult { - let mut stream = try!(TcpStream::connect(host, port)); - - Ok(IrcConnection { - callbacks: callbacks, - stream: stream - }) - } - - pub fn start_loop(&mut self) { - let stream = self.stream.clone(); -// spawn(proc() { - let mut reader = BufferedReader::new(stream); - loop { - match reader.read_line() { - Ok(line) => { - let mut words: Vec<&str> = line.as_slice().words().collect(); - - println!("{}", words); - if words.is_empty() { continue; } - if (*words.get(0)).starts_with(":") { - words.shift(); - } - match *words.get(0) { - "PING" => println!("PING"), - other => println!("other: {}", other), - } - } - Err(e) => { - println!("An Error occured: {}", e); - break; - } - } - break; - } -// }); - } -} - -pub struct IrcCallbacks { - pub on_connect: fn(&mut IrcConnection)->(), - pub on_numeric: fn(&mut IrcConnection, uint, &str, &[&str])->(), - //TODO: Add the rest -} diff --git a/libirc/lib.rs b/libirc/lib.rs new file mode 100644 index 0000000..8b385ec --- /dev/null +++ b/libirc/lib.rs @@ -0,0 +1,86 @@ +#![crate_id = "irc#0.1"] +#![crate_type = "lib"] + +use std::io::net::tcp::TcpStream; +use std::io::IoResult; +use std::io::BufferedReader; +use std::io::IoError; + +use msg::Message; +use msg::cmd; + +pub mod msg; + +pub struct IrcConnection<'a> { + stream: TcpStream, + output_sender: Sender, + msg_callback: |&Message, &Sender|: 'a -> () +} + +impl<'a> IrcConnection<'a> { + pub fn connect<'b>( + host: &str, port: u16, nick: String, username: String, + real_name: String, msg_callback: |&Message, &Sender|: 'b -> ()) -> IoResult> { + + let (send_writer, rec_writer) = channel(); + + let mut connection = IrcConnection { + stream: try!(TcpStream::connect(host, port)), + output_sender: send_writer.clone(), + msg_callback: msg_callback, + }; + + let writer = connection.stream.clone(); + + // spawn writer thread + spawn(proc() { + let mut writer = writer; + for msg in rec_writer.iter() { + (write!(writer, "{}", msg)).ok().expect("Unable to write to stream"); + } + }); + + connection.send(Message::new(cmd::Nick(nick))); + connection.send(Message::new(cmd::User(username, 0, real_name))); + Ok(connection) + } + + pub fn send(&mut self, message: Message) { + self.output_sender.send(message); + } + + fn on_msg_rec(msg: &Message, sender: &Sender) { + let prefix = &msg.prefix; + let cmd = &msg.command; + match *cmd { + cmd::Ping(ref s) => sender.send(Message::new(cmd::Pong(s.clone()))), + _ => { } + }; + } + + pub fn run_loop(&mut self) { + let reader = &mut self.stream; + loop { + fn reader_by_ref<'a, R: Reader>(reader: &'a mut R) -> std::io::RefReader<'a, R> { reader.by_ref() } + + reader.set_read_timeout(Some(500)); + let mut buf_reader = BufferedReader::new(reader_by_ref(reader)); + + let line = buf_reader.read_line(); + match line { + Ok(line) => match from_str::(line.as_slice().trim_right()) { + Some(msg) => { + IrcConnection::on_msg_rec(&msg, &self.output_sender); + (self.msg_callback)(&msg, &self.output_sender); + }, + None => println!("Invalid Message recieved"), + }, + Err(IoError{kind: std::io::TimedOut, ..}) => continue, + Err(e) => { + println!("Unable to read line: {}", e); + break; + } + } + } + } +} diff --git a/libirc/libirc-ad3d5237-0.1.rlib b/libirc/libirc-ad3d5237-0.1.rlib new file mode 100644 index 0000000..c367445 Binary files /dev/null and b/libirc/libirc-ad3d5237-0.1.rlib differ diff --git a/libirc/msg.rs b/libirc/msg.rs new file mode 100644 index 0000000..3471d75 --- /dev/null +++ b/libirc/msg.rs @@ -0,0 +1,185 @@ +use std::fmt; +use std::from_str::FromStr; +use std::ascii::OwnedStrAsciiExt; + +pub mod cmd { + #[deriving(Clone, Show)] + pub enum Command { + Nick(String), + User(String, u8, String), + Quit(Option), + Join(String), + Part(String, Option), + PrivMsg(String, String), + Notice(String, String), + //Motd(Option), + Ping(String), + Pong(String), + Error(String), + Away(Option), + Numeric(u16, Option), + UnknownCmd(String, Vec) + } +} + +pub struct PrefixHost { + hostname: String, + user: Option, +} + +pub enum Prefix { + PrefixServer(String), + PrefixUser(String, Option), +} + +#[deriving(Clone)] +pub struct Message { + pub prefix: Option, + pub command: cmd::Command, +} + +impl Message { + pub fn new(command: cmd::Command) -> Message { + Message { prefix: None, command: command } + } + + pub fn with_prefix(prefix: String, command: cmd::Command) -> Message { + Message { prefix: Some(prefix), command: command } + } +} + +impl<'a> fmt::Show for Message { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + if self.prefix.is_some() { + try!(write!(formatter, ":{} ", self.prefix.get_ref())); + } + + match self.command { + cmd::Nick(ref nickname) => write!(formatter, "NICK {}", nickname), + cmd::User(ref username, mode, ref real_name) => write!(formatter, "USER {} {} * :{}", username, mode, real_name), + cmd::Quit(ref msg) => if msg.is_some() { write!(formatter, "QUIT :{}", *msg.get_ref()) } else { write!(formatter, "QUIT") }, + cmd::Join(ref channel) => write!(formatter, "JOIN :{}", channel), + cmd::Part(ref channel, ref msg) => if msg.is_some() { write!(formatter, "PART {} :{}", channel, *msg.get_ref()) } else { write!(formatter, "PART {}", channel) }, + cmd::PrivMsg(ref target, ref msg) => write!(formatter, "PRIVMSG {} :{}", target, msg), + cmd::Notice(ref target, ref msg) => write!(formatter, "NOTICE {} :{}", target, msg), + cmd::Ping(ref msg) => write!(formatter, "PING :{}", msg), + cmd::Pong(ref msg) => write!(formatter, "PONG :{}", msg), + cmd::Error(ref msg) => write!(formatter, "ERROR :{}", msg), + cmd::Away(ref msg) => if msg.is_some() { write!(formatter, "AWAY :{}", msg.get_ref()) } else { write!(formatter, "AWAY") }, + cmd::Numeric(i, ref msg) => if msg.is_some() { write!(formatter, "{:03u} :{}", i, msg.get_ref()) } else { write!(formatter, "{:03u}", i) }, + cmd::UnknownCmd(ref cmd, ref args) => { + try!(write!(formatter, "{}", cmd)); + let mut iter = args.iter().peekable(); + loop { + match iter.next() { + Some(arg) => { + try!( + if iter.peek().is_some() { + write!(formatter, " {}", arg) + } + else { + write!(formatter, " :{}", arg) + } + ) + } + None => break + } + } + Ok(()) + } + } + } +} + +impl FromStr for Message { + fn from_str(s: &str) -> Option { + let mut prefix = None; + let mut cmd = None; + let mut args = Vec::new(); + let mut current_str: Option = None; + let mut is_prefix = false; + let mut is_final = false; + + for c in s.chars() { + match c { + c if is_final => { + current_str.get_mut_ref().push_char(c); + } + ' ' => { + if is_prefix { + prefix = current_str.take(); + } + else if cmd.is_none() { + cmd = current_str.take(); + } + else { + args.push(current_str.take_unwrap()); + } + is_prefix = false; + } + ':' if current_str.is_none() => { + current_str = Some(String::new()); + if cmd.is_none() { + is_prefix = true; + } + else { + is_final = true; + } + } + c => { + if current_str.is_none() { + current_str = Some(String::new()); + } + current_str.get_mut_ref().push_char(c) + } + } + } + + args.push(current_str.take_unwrap()); + + let cmd = match cmd.map(|s| s.into_ascii_upper()).as_ref().map(|s| s.as_slice()) { + Some("NICK") => { + if args.len() == 1 { Some(cmd::Nick(args.pop().unwrap())) } + else { None } + } + Some("USER") => { + if args.len() == 4 { + let mut iter = args.move_iter(); + let uname = iter.next().unwrap(); + let opt_mode: Option = from_str(iter.next().unwrap().as_slice()); + iter.next(); + let fullname = iter.next().unwrap(); + if opt_mode.is_some() { + Some(cmd::User(uname, opt_mode.unwrap(), fullname)) + } + else { + None + } + } + else { None } + } + Some("NOTICE") => { + if args.len() == 2 { + let mut iter = args.move_iter(); + Some(cmd::Notice(iter.next().unwrap(), iter.next().unwrap())) + } + else { None } + } + Some("PRIVMSG") => { + if args.len() == 2 { + let mut iter = args.move_iter(); + Some(cmd::PrivMsg(iter.next().unwrap(), iter.next().unwrap())) + } + else { None } + } + Some(other) => { + Some(cmd::UnknownCmd(other.to_string(), args)) + } + None => { + None + } + }; + + cmd.map(|c| Message { prefix: prefix.take(), command: c }) + } +} diff --git a/main.rs b/main.rs index 1d975b2..6ec9134 100644 --- a/main.rs +++ b/main.rs @@ -1,24 +1,25 @@ +extern crate irc; + use std::io::net::tcp::TcpStream; use std::io::BufferedReader; -use lib::IrcCallbacks; -use lib::IrcConnection; - -mod lib; +use irc::IrcConnection; +use irc::msg::Message; +use irc::msg::cmd; fn main() { - fn on_connect(_connection: &mut IrcConnection) { - println!("Connected"); - } - fn on_numeric(_connection: &mut IrcConnection, n: uint, origin: &str, params: &[&str]) { - println!("Numeric event \\#{} with params {}", n, params); - } - let callbacks = IrcCallbacks { - on_connect: on_connect, - on_numeric: on_numeric, + let message = Message { + prefix: None, + command: cmd::PrivMsg("#rust".to_string(), "Hi there everyone".to_string()), + }; + + println!("{}", message); + + let on_msg = |message: &Message, _sender: &Sender| { + println!("{}", *message); }; - let mut connection = IrcConnection::connect(callbacks, "irc.mozilla.org", 6667, "Dr-Emann", "dremann", "Zachary Dremann").unwrap(); - connection.start_loop(); + let mut connection = IrcConnection::connect("irc.mozilla.org", 6667, "Dr-Emann".to_string(), "dremann".to_string(), "Zachary Dremann".to_string(), on_msg).unwrap(); + connection.run_loop(); } -- cgit v1.2.3-54-g00ecf