From e1d4270acbb12306f5e30927b4f05ff2ff6c6937 Mon Sep 17 00:00:00 2001 From: Till Hoeppner Date: Mon, 4 May 2015 20:09:59 +0200 Subject: Add SSL connections and use them in the example --- examples/01.rs | 15 +++++++++++++-- src/client.rs | 22 ++++++++++++++-------- src/lib.rs | 14 +++++++++++++- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/examples/01.rs b/examples/01.rs index 345adba..595bc70 100644 --- a/examples/01.rs +++ b/examples/01.rs @@ -1,4 +1,5 @@ extern crate irsc; +extern crate env_logger; use std::borrow::ToOwned; use std::borrow::Cow::*; @@ -20,7 +21,12 @@ fn callback(server: &mut Client, msg: &Message) { MsgType::Irc => format!("{} wrote: {}", from.nickname, bold(&content)), MsgType::Ctcp => format!("{} emoted: {}", from.nickname, bold(&content["ACTION ".len()..])) }; - server.send(PRIVMSG(to, Owned(response))).unwrap(); + + // only send to channels, to prevent recursion when we are pm'ed + // technically, there are other prefixes than '#', but ignoring them is fine + if to.starts_with("#") { + server.send(PRIVMSG(to, Owned(response))).unwrap(); + } }, _ => () } @@ -34,8 +40,13 @@ fn callback(server: &mut Client, msg: &Message) { } fn main() { + env_logger::init().unwrap(); let mut s = Client::new(); - s.connect("irc.mozilla.org".to_owned(), 6667).unwrap(); + if cfg!(feature = "ssl") { + s.connect_ssl("irc.mozilla.org".to_owned(), 6697).unwrap(); + } else { + s.connect("irc.mozilla.org".to_owned(), 6667).unwrap(); + } s.send(NICK(Borrowed(NAME))).unwrap(); s.send(USER(Borrowed(NAME), Borrowed("*"), Borrowed("*"), Borrowed(DESC))).unwrap(); diff --git a/src/client.rs b/src/client.rs index a738262..a688565 100644 --- a/src/client.rs +++ b/src/client.rs @@ -20,7 +20,7 @@ use openssl::ssl::{ SslContext, SslMethod, SslStream }; enum StreamKind { Plain(TcpStream), #[cfg(feature = "ssl")] - Ssl(SslStream) + Ssl(SslStream) } impl Write for StreamKind { @@ -82,18 +82,24 @@ impl Client { #[cfg(feature = "ssl")] pub fn connect_ssl(&mut self, host: String, port: u16) -> Result<()> { - let mut s = self.stream.lock(); + let s = &mut self.stream; match *s { Some(_) => return Err(IrscError::AlreadyConnected), _ => () }; let tcp_stream = match TcpStream::connect((host.as_ref(), port)) { Ok(tcp) => Some(tcp), Err(e) => return Err(IrscError::Io(e)) }; - let ssl = SslContext::new(SslMethod::Tlsv1); - let ssl_stream = SslStream::new(&ssl, tcp_stream); - *s = ssl_stream; + let ssl = try!(SslContext::new(SslMethod::Tlsv1)); + match tcp_stream.map(|tcp| SslStream::new(&ssl, tcp)) { + Some(Ok(ssl_stream)) => { *s = Some(StreamKind::Ssl(ssl_stream)); Ok(()) }, + Some(Err(ssl_error)) => Err(IrscError::Ssl(ssl_error)), + None => Err(IrscError::NotConnected) + } + } - Ok(()) + #[cfg(not(feature = "ssl"))] + pub fn connect_ssl(&mut self, _host: String, _port: u16) -> Result<()> { + panic!("Not compiled with ssl feature.") } #[inline] @@ -121,9 +127,9 @@ impl Client { pub fn listen(&mut self, events: F) -> Result<()> where F: Fn(&mut Client, &Message) { let reader = BufReader::new(match self.stream { - Some(StreamKind::Plain(ref s)) => (*s).try_clone().unwrap(), + Some(StreamKind::Plain(ref s)) => StreamKind::Plain((*s).try_clone().unwrap()), #[cfg(feature = "ssl")] - Some(StreamKind::Ssl(ref s)) => (*s).try_clone().unwrap(), + Some(StreamKind::Ssl(ref s)) => StreamKind::Ssl((*s).try_clone().unwrap()), None => return Err(IrscError::NotConnected) }); diff --git a/src/lib.rs b/src/lib.rs index a4da317..6ec60db 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,8 @@ extern crate regex; #[macro_use] extern crate log; +#[cfg(feature = "ssl")] +extern crate openssl; pub mod client; pub mod color; @@ -19,6 +21,9 @@ pub mod reply; use std::io; use std::result; +#[cfg(feature = "ssl")] +use openssl::ssl::error::SslError; + pub use ident::Ident; pub use message::{ Message, MsgType }; pub use command::Command; @@ -29,7 +34,14 @@ pub enum IrscError { Io(io::Error), AlreadyConnected, NotConnected, - NotFound + NotFound, + #[cfg(feature = "ssl")] + Ssl(SslError) +} + +#[cfg(feature = "ssl")] +impl From for IrscError { + fn from(e: SslError) -> IrscError { IrscError::Ssl(e) } } pub type Result = result::Result; -- cgit v1.2.3