Skip to content

Instantly share code, notes, and snippets.

@mathieulegrand
Last active March 10, 2018 19:57
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save mathieulegrand/9596672 to your computer and use it in GitHub Desktop.
Save mathieulegrand/9596672 to your computer and use it in GitHub Desktop.
simple connect to server:443 in Rust
// 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