parent
d04c4ef435
commit
a7dab3624e
|
|
@ -1,6 +1,6 @@
|
||||||
#[doc(hidden)];
|
#[doc(hidden)];
|
||||||
|
|
||||||
use std::libc::{c_int, c_long, c_void};
|
use std::libc::{c_int, c_void};
|
||||||
|
|
||||||
// openssl/ssl.h
|
// openssl/ssl.h
|
||||||
pub type SSL_CTX = c_void;
|
pub type SSL_CTX = c_void;
|
||||||
|
|
@ -35,6 +35,8 @@ externfn!(fn SSL_set_bio(ssl: *SSL, rbio: *BIO, wbio: *BIO))
|
||||||
externfn!(fn SSL_set_connect_state(ssl: *SSL))
|
externfn!(fn SSL_set_connect_state(ssl: *SSL))
|
||||||
externfn!(fn SSL_connect(ssl: *SSL) -> c_int)
|
externfn!(fn SSL_connect(ssl: *SSL) -> c_int)
|
||||||
externfn!(fn SSL_get_error(ssl: *SSL, ret: c_int) -> c_int)
|
externfn!(fn SSL_get_error(ssl: *SSL, ret: c_int) -> c_int)
|
||||||
|
externfn!(fn SSL_read(ssl: *SSL, buf: *c_void, num: c_int) -> c_int)
|
||||||
|
externfn!(fn SSL_write(ssl: *SSL, buf: *c_void, num: c_int) -> c_int)
|
||||||
|
|
||||||
externfn!(fn BIO_s_mem() -> *BIO_METHOD)
|
externfn!(fn BIO_s_mem() -> *BIO_METHOD)
|
||||||
externfn!(fn BIO_new(type_: *BIO_METHOD) -> *BIO)
|
externfn!(fn BIO_new(type_: *BIO_METHOD) -> *BIO)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::rt::io::{Stream, Decorator};
|
use std::rt::io::{Reader, Writer, Stream, Decorator};
|
||||||
use std::unstable::atomics::{AtomicBool, INIT_ATOMIC_BOOL, Acquire, Release};
|
use std::unstable::atomics::{AtomicBool, INIT_ATOMIC_BOOL, Acquire, Release};
|
||||||
use std::task;
|
use std::task;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
@ -70,6 +70,7 @@ impl Drop for Ssl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deriving(Eq, TotalEq, ToStr)]
|
||||||
enum SslError {
|
enum SslError {
|
||||||
ErrorNone,
|
ErrorNone,
|
||||||
ErrorSsl,
|
ErrorSsl,
|
||||||
|
|
@ -114,6 +115,20 @@ impl Ssl {
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read(&self, buf: &[u8]) -> int {
|
||||||
|
unsafe {
|
||||||
|
ffi::SSL_read(self.ssl, vec::raw::to_ptr(buf) as *c_void,
|
||||||
|
buf.len() as c_int) as int
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&self, buf: &[u8]) -> int {
|
||||||
|
unsafe {
|
||||||
|
ffi::SSL_write(self.ssl, vec::raw::to_ptr(buf) as *c_void,
|
||||||
|
buf.len() as c_int) as int
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MemBio {
|
struct MemBio {
|
||||||
|
|
@ -150,11 +165,12 @@ impl MemBio {
|
||||||
let ret = ffi::BIO_read(self.bio, vec::raw::to_ptr(buf) as *c_void,
|
let ret = ffi::BIO_read(self.bio, vec::raw::to_ptr(buf) as *c_void,
|
||||||
buf.len() as c_int);
|
buf.len() as c_int);
|
||||||
if ret < 0 {
|
if ret < 0 {
|
||||||
fail2!("read returned {}", ret);
|
0
|
||||||
}
|
} else {
|
||||||
ret as uint
|
ret as uint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SslStream<S> {
|
pub struct SslStream<S> {
|
||||||
|
|
@ -179,47 +195,86 @@ impl<S: Stream> SslStream<S> {
|
||||||
let mut stream = SslStream {
|
let mut stream = SslStream {
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
ssl: ssl,
|
ssl: ssl,
|
||||||
|
// Max record size for SSLv3/TLSv1 is 16k
|
||||||
buf: vec::from_elem(16 * 1024, 0u8),
|
buf: vec::from_elem(16 * 1024, 0u8),
|
||||||
rbio: rbio,
|
rbio: rbio,
|
||||||
wbio: wbio,
|
wbio: wbio,
|
||||||
stream: stream
|
stream: stream
|
||||||
};
|
};
|
||||||
|
|
||||||
stream.connect();
|
do stream.in_retry_wrapper |ssl| {
|
||||||
|
ssl.ssl.connect()
|
||||||
|
};
|
||||||
|
|
||||||
stream
|
stream
|
||||||
}
|
}
|
||||||
|
|
||||||
fn connect(&mut self) {
|
fn in_retry_wrapper(&mut self, blk: &fn(&mut SslStream<S>) -> int)
|
||||||
info!("in connect");
|
-> Result<int, SslError> {
|
||||||
loop {
|
loop {
|
||||||
let ret = self.ssl.connect();
|
let ret = blk(self);
|
||||||
info2!("connect returned {}", ret);
|
if ret > 0 {
|
||||||
if ret == 1 {
|
return Ok(ret);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.ssl.get_error(ret) {
|
match self.ssl.get_error(ret) {
|
||||||
ErrorWantRead => {
|
ErrorWantRead => {
|
||||||
info2!("want read");
|
|
||||||
self.flush();
|
self.flush();
|
||||||
match self.stream.read(self.buf) {
|
match self.stream.read(self.buf) {
|
||||||
Some(len) => self.rbio.write(self.buf.slice_to(len)),
|
Some(len) => self.rbio.write(self.buf.slice_to(len)),
|
||||||
None => unreachable!()
|
None => unreachable!() // FIXME
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ErrorWantWrite => {
|
ErrorWantWrite => self.flush(),
|
||||||
info2!("want write");
|
err => return Err(err)
|
||||||
self.flush();
|
|
||||||
}
|
|
||||||
_ => unreachable!()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&mut self) {
|
fn write_through(&mut self) {
|
||||||
|
loop {
|
||||||
let len = self.wbio.read(self.buf);
|
let len = self.wbio.read(self.buf);
|
||||||
|
if len == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
self.stream.write(self.buf.slice_to(len));
|
self.stream.write(self.buf.slice_to(len));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: Stream> Reader for SslStream<S> {
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
|
||||||
|
let ret = do self.in_retry_wrapper |ssl| {
|
||||||
|
ssl.ssl.read(buf)
|
||||||
|
};
|
||||||
|
|
||||||
|
match ret {
|
||||||
|
Ok(num) => Some(num as uint),
|
||||||
|
Err(_) => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eof(&mut self) -> bool {
|
||||||
|
self.stream.eof()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: Stream> Writer for SslStream<S> {
|
||||||
|
fn write(&mut self, buf: &[u8]) {
|
||||||
|
let ret = do self.in_retry_wrapper |ssl| {
|
||||||
|
ssl.ssl.write(buf)
|
||||||
|
};
|
||||||
|
|
||||||
|
match ret {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(err) => fail2!("Write error: {}", err.to_str())
|
||||||
|
}
|
||||||
|
|
||||||
|
self.write_through();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) {
|
||||||
|
self.write_through();
|
||||||
self.stream.flush();
|
self.stream.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
extern mod ssl;
|
extern mod ssl;
|
||||||
|
|
||||||
|
use std::rt::io::{Writer};
|
||||||
use std::rt::io::net::tcp::TcpStream;
|
use std::rt::io::net::tcp::TcpStream;
|
||||||
|
use std::vec;
|
||||||
|
|
||||||
use ssl::{Sslv23, SslCtx, SslStream};
|
use ssl::{Sslv23, SslCtx, SslStream};
|
||||||
|
|
||||||
|
|
@ -14,3 +16,11 @@ fn test_new_sslstream() {
|
||||||
let stream = TcpStream::connect(FromStr::from_str("127.0.0.1:15418").unwrap());
|
let stream = TcpStream::connect(FromStr::from_str("127.0.0.1:15418").unwrap());
|
||||||
SslStream::new(SslCtx::new(Sslv23), stream);
|
SslStream::new(SslCtx::new(Sslv23), stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_write() {
|
||||||
|
let stream = TcpStream::connect(FromStr::from_str("127.0.0.1:15418").unwrap());
|
||||||
|
let mut stream = SslStream::new(SslCtx::new(Sslv23), stream);
|
||||||
|
stream.write("hello".as_bytes());
|
||||||
|
stream.flush();
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue