Added SSL support, but it's broken because of the duplicate SslStream creations.
This commit is contained in:
parent
a79a1fc033
commit
a903dd9571
8 changed files with 141 additions and 12 deletions
|
@ -9,3 +9,12 @@ keywords = ["irc", "client", "thread-safe"]
|
||||||
documentation = "http://www.rust-ci.org/aaronweiss74/irc/doc/irc/"
|
documentation = "http://www.rust-ci.org/aaronweiss74/irc/doc/irc/"
|
||||||
repository = "https://github.com/aaronweiss74/irc"
|
repository = "https://github.com/aaronweiss74/irc"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
|
||||||
|
ssl = ["openssl"]
|
||||||
|
|
||||||
|
[dependencies.openssl]
|
||||||
|
|
||||||
|
git = "https://github.com/sfackler/rust-openssl.git"
|
||||||
|
optional = true
|
||||||
|
|
|
@ -16,6 +16,7 @@ fn main() {
|
||||||
password: "".into_string(),
|
password: "".into_string(),
|
||||||
server: "irc.fyrechat.net".into_string(),
|
server: "irc.fyrechat.net".into_string(),
|
||||||
port: 6667,
|
port: 6667,
|
||||||
|
use_ssl: false,
|
||||||
channels: vec!("#vana".into_string()),
|
channels: vec!("#vana".into_string()),
|
||||||
options: HashMap::new(),
|
options: HashMap::new(),
|
||||||
};
|
};
|
||||||
|
|
36
examples/simple_ssl.rs
Normal file
36
examples/simple_ssl.rs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#![feature(if_let)]
|
||||||
|
#![feature(slicing_syntax)]
|
||||||
|
extern crate irc;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use irc::data::config::Config;
|
||||||
|
use irc::server::{IrcServer, Server};
|
||||||
|
use irc::server::utils::Wrapper;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let config = Config {
|
||||||
|
owners: vec!("awe".into_string()),
|
||||||
|
nickname: "pickles".into_string(),
|
||||||
|
username: "pickles".into_string(),
|
||||||
|
realname: "pickles".into_string(),
|
||||||
|
password: "".into_string(),
|
||||||
|
server: "irc.fyrechat.net".into_string(),
|
||||||
|
port: 6697,
|
||||||
|
use_ssl: true,
|
||||||
|
channels: vec!("#vana".into_string()),
|
||||||
|
options: HashMap::new(),
|
||||||
|
};
|
||||||
|
let irc_server = IrcServer::from_config(config).unwrap();
|
||||||
|
let server = Wrapper::new(&irc_server);
|
||||||
|
server.identify().unwrap();
|
||||||
|
for message in server.iter() {
|
||||||
|
print!("{}", message.into_string());
|
||||||
|
if message.command[] == "PRIVMSG" {
|
||||||
|
if let Some(msg) = message.suffix {
|
||||||
|
if msg.contains("pickles") {
|
||||||
|
server.send_privmsg(message.args[0][], "Hi!").unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +1 @@
|
||||||
echo "{\"owners\": [\"test\"],\"nickname\": \"test\",\"username\": \"test\",\"realname\": \"test\",\"password\": \"\",\"server\": \"irc.test.net\",\"port\": 6667,\"channels\": [\"#test\", \"#test2\"],\"options\": {}}" > config.json
|
echo "{\"owners\": [\"test\"],\"nickname\": \"test\",\"username\": \"test\",\"realname\": \"test\",\"password\": \"\",\"server\": \"irc.test.net\",\"port\": 6667,\"use_ssl\": false,\"channels\": [\"#test\", \"#test2\"],\"options\": {}}" > config.json
|
||||||
|
|
72
src/conn.rs
72
src/conn.rs
|
@ -2,8 +2,11 @@
|
||||||
#![experimental]
|
#![experimental]
|
||||||
use std::sync::{Mutex, MutexGuard};
|
use std::sync::{Mutex, MutexGuard};
|
||||||
use std::io::{BufferedReader, BufferedWriter, IoResult, TcpStream};
|
use std::io::{BufferedReader, BufferedWriter, IoResult, TcpStream};
|
||||||
|
#[cfg(feature = "ssl")] use std::io::{IoError, OtherIoError};
|
||||||
use data::kinds::{IrcWriter, IrcReader};
|
use data::kinds::{IrcWriter, IrcReader};
|
||||||
use data::message::Message;
|
use data::message::Message;
|
||||||
|
#[cfg(feature = "ssl")] use openssl::ssl::{SslContext, SslStream, Tlsv1};
|
||||||
|
#[cfg(feature = "ssl")] use openssl::ssl::error::SslError;
|
||||||
|
|
||||||
/// A thread-safe connection.
|
/// A thread-safe connection.
|
||||||
#[experimental]
|
#[experimental]
|
||||||
|
@ -15,9 +18,74 @@ pub struct Connection<T, U> where T: IrcWriter, U: IrcReader {
|
||||||
impl Connection<BufferedWriter<TcpStream>, BufferedReader<TcpStream>> {
|
impl Connection<BufferedWriter<TcpStream>, BufferedReader<TcpStream>> {
|
||||||
/// Creates a thread-safe TCP connection to the specified server.
|
/// Creates a thread-safe TCP connection to the specified server.
|
||||||
#[experimental]
|
#[experimental]
|
||||||
pub fn connect(host: &str, port: u16) -> IoResult<Connection<BufferedWriter<TcpStream>, BufferedReader<TcpStream>>> {
|
pub fn connect(host: &str, port: u16) -> IoResult<Connection<BufferedWriter<NetStream>, BufferedReader<NetStream>>> {
|
||||||
let socket = try!(TcpStream::connect(format!("{}:{}", host, port)[]));
|
let socket = try!(TcpStream::connect(format!("{}:{}", host, port)[]));
|
||||||
Ok(Connection::new(BufferedWriter::new(socket.clone()), BufferedReader::new(socket)))
|
Ok(Connection::new(BufferedWriter::new(UnsecuredTcpStream(socket.clone())),
|
||||||
|
BufferedReader::new(UnsecuredTcpStream(socket))))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a thread-safe TCP connection to the specified server over SSL.
|
||||||
|
/// If the library is compiled without SSL support, this method panics.
|
||||||
|
#[experimental]
|
||||||
|
#[cfg(feature = "ssl")]
|
||||||
|
pub fn connect_ssl(host: &str, port: u16) -> IoResult<Connection<BufferedWriter<NetStream>, BufferedReader<NetStream>>> {
|
||||||
|
let socket = try!(TcpStream::connect(format!("{}:{}", host, port)[]));
|
||||||
|
let ssl = try!(ssl_to_io(SslContext::new(Tlsv1)));
|
||||||
|
let input = try!(ssl_to_io(SslStream::new(&ssl, socket.clone())));
|
||||||
|
let output = try!(ssl_to_io(SslStream::new(&ssl, socket)));
|
||||||
|
Ok(Connection::new(BufferedWriter::new(SslTcpStream(input)),
|
||||||
|
BufferedReader::new(SslTcpStream(output))))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a thread-safe TCP connection to the specified server over SSL.
|
||||||
|
/// If the library is compiled without SSL support, this method panics.
|
||||||
|
#[experimental]
|
||||||
|
#[cfg(not(feature = "ssl"))]
|
||||||
|
pub fn connect_ssl(host: &str, port: u16) -> IoResult<Connection<BufferedWriter<NetStream>, BufferedReader<NetStream>>> {
|
||||||
|
panic!("Cannot connect to {}:{} over SSL without compiling with SSL support.", host, port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An abstraction over different networked streams.
|
||||||
|
#[experimental]
|
||||||
|
pub enum NetStream {
|
||||||
|
/// An unsecured TcpStream.
|
||||||
|
UnsecuredTcpStream(TcpStream),
|
||||||
|
/// An SSL-secured TcpStream.
|
||||||
|
/// This is only available when compiled with SSL support.
|
||||||
|
#[cfg(feature = "ssl")]
|
||||||
|
SslTcpStream(SslStream<TcpStream>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Reader for NetStream {
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
|
||||||
|
match self {
|
||||||
|
&UnsecuredTcpStream(ref mut stream) => stream.read(buf),
|
||||||
|
#[cfg(feature = "ssl")]
|
||||||
|
&SslTcpStream(ref mut stream) => stream.read(buf),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Writer for NetStream {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
|
||||||
|
match self {
|
||||||
|
&UnsecuredTcpStream(ref mut stream) => stream.write(buf),
|
||||||
|
#[cfg(feature = "ssl")]
|
||||||
|
&SslTcpStream(ref mut stream) => stream.write(buf),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ssl")]
|
||||||
|
fn ssl_to_io<T>(res: Result<T, SslError>) -> IoResult<T> {
|
||||||
|
match res {
|
||||||
|
Ok(x) => Ok(x),
|
||||||
|
Err(e) => Err(IoError {
|
||||||
|
kind: OtherIoError,
|
||||||
|
desc: "An SSL error occurred.",
|
||||||
|
detail: Some(format!("{}", e)),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,8 @@ pub struct Config {
|
||||||
pub server: String,
|
pub server: String,
|
||||||
/// The port to connect on.
|
/// The port to connect on.
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
|
/// Whether or not to use SSL.
|
||||||
|
pub use_ssl: bool,
|
||||||
/// A list of channels to join on connection.
|
/// A list of channels to join on connection.
|
||||||
pub channels: Vec<String>,
|
pub channels: Vec<String>,
|
||||||
/// A map of additional options to be stored in config.
|
/// A map of additional options to be stored in config.
|
||||||
|
@ -70,6 +72,7 @@ mod test {
|
||||||
password: String::new(),
|
password: String::new(),
|
||||||
server: format!("irc.test.net"),
|
server: format!("irc.test.net"),
|
||||||
port: 6667,
|
port: 6667,
|
||||||
|
use_ssl: false,
|
||||||
channels: vec![format!("#test"), format!("#test2")],
|
channels: vec![format!("#test"), format!("#test2")],
|
||||||
options: HashMap::new(),
|
options: HashMap::new(),
|
||||||
};
|
};
|
||||||
|
@ -86,6 +89,7 @@ mod test {
|
||||||
password: String::new(),
|
password: String::new(),
|
||||||
server: format!("irc.test.net"),
|
server: format!("irc.test.net"),
|
||||||
port: 6667,
|
port: 6667,
|
||||||
|
use_ssl: false,
|
||||||
channels: vec![format!("#test"), format!("#test2")],
|
channels: vec![format!("#test"), format!("#test2")],
|
||||||
options: HashMap::new(),
|
options: HashMap::new(),
|
||||||
};
|
};
|
||||||
|
@ -102,6 +106,7 @@ mod test {
|
||||||
password: String::new(),
|
password: String::new(),
|
||||||
server: format!("irc.test.net"),
|
server: format!("irc.test.net"),
|
||||||
port: 6667,
|
port: 6667,
|
||||||
|
use_ssl: false,
|
||||||
channels: Vec::new(),
|
channels: Vec::new(),
|
||||||
options: HashMap::new(),
|
options: HashMap::new(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#![feature(if_let)]
|
#![feature(if_let)]
|
||||||
#![feature(slicing_syntax)]
|
#![feature(slicing_syntax)]
|
||||||
extern crate serialize;
|
extern crate serialize;
|
||||||
|
#[cfg(feature = "ssl")] extern crate openssl;
|
||||||
|
|
||||||
pub mod conn;
|
pub mod conn;
|
||||||
pub mod data;
|
pub mod data;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! Interface for working with IRC Servers
|
//! Interface for working with IRC Servers
|
||||||
#![experimental]
|
#![experimental]
|
||||||
use std::io::{BufferedReader, BufferedWriter, IoResult, TcpStream};
|
use std::io::{BufferedReader, BufferedWriter, IoResult};
|
||||||
use conn::Connection;
|
use conn::{Connection, NetStream};
|
||||||
use data::command::{Command, JOIN, PONG};
|
use data::command::{Command, JOIN, PONG};
|
||||||
use data::config::Config;
|
use data::config::Config;
|
||||||
use data::kinds::{IrcReader, IrcWriter};
|
use data::kinds::{IrcReader, IrcWriter};
|
||||||
|
@ -29,20 +29,28 @@ pub struct IrcServer<'a, T, U> where T: IrcWriter, U: IrcReader {
|
||||||
config: Config
|
config: Config
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> IrcServer<'a, BufferedWriter<TcpStream>, BufferedReader<TcpStream>> {
|
impl<'a> IrcServer<'a, BufferedWriter<NetStream>, BufferedReader<NetStream>> {
|
||||||
/// Creates a new IRC Server connection from the configuration at the specified path, connecting immediately.
|
/// Creates a new IRC Server connection from the configuration at the specified path, connecting immediately.
|
||||||
#[experimental]
|
#[experimental]
|
||||||
pub fn new(config: &str) -> IoResult<IrcServer<'a, BufferedWriter<TcpStream>, BufferedReader<TcpStream>>> {
|
pub fn new(config: &str) -> IoResult<IrcServer<'a, BufferedWriter<NetStream>, BufferedReader<NetStream>>> {
|
||||||
let config = try!(Config::load_utf8(config));
|
let config = try!(Config::load_utf8(config));
|
||||||
let conn = try!(Connection::connect(config.server[], config.port));
|
let conn = try!(if config.use_ssl {
|
||||||
Ok(IrcServer::from_connection(config, conn))
|
Connection::connect_ssl(config.server[], config.port)
|
||||||
|
} else {
|
||||||
|
Connection::connect(config.server[], config.port)
|
||||||
|
});
|
||||||
|
Ok(IrcServer { config: config, conn: conn })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new IRC server connection from the specified configuration, connecting immediately.
|
/// Creates a new IRC server connection from the specified configuration, connecting immediately.
|
||||||
#[experimental]
|
#[experimental]
|
||||||
pub fn from_config(config: Config) -> IoResult<IrcServer<'a, BufferedWriter<TcpStream>, BufferedReader<TcpStream>>> {
|
pub fn from_config(config: Config) -> IoResult<IrcServer<'a, BufferedWriter<NetStream>, BufferedReader<NetStream>>> {
|
||||||
let conn = try!(Connection::connect(config.server[], config.port));
|
let conn = try!(if config.use_ssl {
|
||||||
Ok(IrcServer::from_connection(config, conn))
|
Connection::connect_ssl(config.server[], config.port)
|
||||||
|
} else {
|
||||||
|
Connection::connect(config.server[], config.port)
|
||||||
|
});
|
||||||
|
Ok(IrcServer { config: config, conn: conn })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,6 +147,7 @@ mod test {
|
||||||
password: String::new(),
|
password: String::new(),
|
||||||
server: format!("irc.test.net"),
|
server: format!("irc.test.net"),
|
||||||
port: 6667,
|
port: 6667,
|
||||||
|
use_ssl: false,
|
||||||
channels: vec![format!("#test"), format!("#test2")],
|
channels: vec![format!("#test"), format!("#test2")],
|
||||||
options: HashMap::new(),
|
options: HashMap::new(),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue