Last active
March 10, 2018 19:57
-
-
Save mathieulegrand/9596672 to your computer and use it in GitHub Desktop.
simple connect to server:443 in Rust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Rust 0.10-pre (Tue Mar 18, 2014) | |
// $ rustc -L rust-openssl/build/ -L rust-toml/lib doing.rs | |
// assuming https://github.com/sfackler/rust-openssl is cloned and compiled, | |
// and https://github.com/mneumann/rust-tom is cloned and compiled | |
#[feature(macro_rules)]; | |
#[allow(deprecated_owned_vector)]; | |
extern crate openssl; | |
extern crate serialize; | |
extern crate toml = "github.com/mneumann/rust-toml#toml:0.1"; | |
use std::io::net; | |
use std::io::net::ip::{Port,SocketAddr}; | |
use std::io::net::tcp::TcpStream; | |
use std::io::{BufferedStream, IoResult}; | |
use openssl::ssl::{Sslv23, SslContext, SslStream}; | |
use std::str; | |
macro_rules! if_ok_conn( | |
($e:expr, $($t:tt)*) => ( | |
match $e { | |
Ok(ok) => ok, | |
Err(err) => { fail!("{:s}{:s}", $($t)*, err.to_str()); } | |
} | |
) | |
) | |
static DEFAULT_PORT: Port = 443; | |
#[deriving(Show)] | |
pub enum ConnectError { | |
DnsError, | |
SocketError, | |
} | |
#[deriving(Show,Decodable)] | |
struct Config { | |
host: ~str, | |
port: Option<u16> | |
} | |
enum InternalStream { | |
Normal(TcpStream), | |
Ssl(SslStream<TcpStream>) | |
} | |
impl Reader for InternalStream { | |
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { | |
match *self { | |
Normal(ref mut s) => s.read(buf), | |
Ssl(ref mut s) => s.read(buf) | |
} | |
} | |
} | |
impl Writer for InternalStream { | |
fn write(&mut self, buf: &[u8]) -> IoResult<()> { | |
match *self { | |
Normal(ref mut s) => s.write(buf), | |
Ssl(ref mut s) => s.write(buf) | |
} | |
} | |
fn flush(&mut self) -> IoResult<()> { | |
match *self { | |
Normal(ref mut s) => s.flush(), | |
Ssl(ref mut s) => s.flush() | |
} | |
} | |
} | |
fn open_socket(host: &str, port: Port) -> Result<TcpStream, ConnectError> { | |
let addrs = match net::get_host_addresses(host) { | |
Ok(addrs) => addrs, | |
Err(_) => return Err(DnsError) | |
}; | |
for &addr in addrs.iter() { | |
match TcpStream::connect(SocketAddr{ ip: addr, port: port }) { | |
Ok(socket) => return Ok(socket), | |
Err(_) => {} // just loop on error to the next IP | |
} | |
} | |
Err(SocketError) | |
} | |
fn open_stream(host: &str, port: Port) -> Result<InternalStream, ConnectError> { | |
// try SSL first | |
let ssl_socket = if_ok_conn!(open_socket(host, port), "error opening socker: "); | |
match SslStream::try_new(&SslContext::new(Sslv23), ssl_socket) { | |
Ok(s) => return Ok(Ssl(s)), | |
Err(_) => {} // failed SSL will try Normal | |
} | |
match open_socket(host, port) { | |
Ok(s) => Ok(Normal(s)), | |
Err(e) => Err(e) | |
} | |
} | |
fn main() { | |
let root = match toml::parse_from_file("doing.toml") { | |
Ok(v) => v, | |
Err(toml::ParseError) => fail!("Config parse error"), | |
Err(toml::IOError(e)) => fail!("Config I/O error: {:s}", e.to_str()) | |
}; | |
let cfg: Config = toml::from_toml(root); | |
let port = cfg.port.unwrap_or(DEFAULT_PORT); | |
println!("Connecting to {:s}:{:u}", cfg.host, port); | |
// Connect the socket | |
let mut stream = if_ok_conn!(open_stream(cfg.host, port), "error opening stream: "); | |
// Get something | |
stream.write("GET /\r\n\r\n".as_bytes()).unwrap(); | |
stream.flush().unwrap(); | |
let buf = stream.read_to_end().ok().expect("read error"); | |
print!("{}", str::from_utf8(buf)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment