aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ssl/ffi.rs2
-rw-r--r--src/ssl/lib.rs49
-rw-r--r--src/ssl/test.rs9
3 files changed, 39 insertions, 21 deletions
diff --git a/src/ssl/ffi.rs b/src/ssl/ffi.rs
index e12bb3c2..f87625ba 100644
--- a/src/ssl/ffi.rs
+++ b/src/ssl/ffi.rs
@@ -37,9 +37,9 @@ externfn!(fn SSL_connect(ssl: *SSL) -> 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 SSL_shutdown(ssl: *SSL) -> c_int)
externfn!(fn BIO_s_mem() -> *BIO_METHOD)
externfn!(fn BIO_new(type_: *BIO_METHOD) -> *BIO)
-externfn!(fn BIO_free(a: *BIO) -> c_int)
externfn!(fn BIO_read(b: *BIO, buf: *c_void, len: c_int) -> c_int)
externfn!(fn BIO_write(b: *BIO, buf: *c_void, len: c_int) -> c_int)
diff --git a/src/ssl/lib.rs b/src/ssl/lib.rs
index 5cc59330..4d79152b 100644
--- a/src/ssl/lib.rs
+++ b/src/ssl/lib.rs
@@ -1,3 +1,5 @@
+#[link(name="ssl")];
+
use std::rt::io::{Reader, Writer, Stream, Decorator};
use std::unstable::atomics::{AtomicBool, INIT_ATOMIC_BOOL, Acquire, Release};
use std::task;
@@ -60,16 +62,6 @@ impl SslCtx {
}
}
-struct Ssl {
- ssl: *ffi::SSL
-}
-
-impl Drop for Ssl {
- fn drop(&mut self) {
- unsafe { ffi::SSL_free(self.ssl); }
- }
-}
-
#[deriving(Eq, TotalEq, ToStr)]
enum SslError {
ErrorNone,
@@ -77,11 +69,22 @@ enum SslError {
ErrorWantRead,
ErrorWantWrite,
ErrorWantX509Lookup,
+ ErrorSyscall,
ErrorZeroReturn,
ErrorWantConnect,
ErrorWantAccept,
}
+struct Ssl {
+ ssl: *ffi::SSL
+}
+
+impl Drop for Ssl {
+ fn drop(&mut self) {
+ unsafe { ffi::SSL_free(self.ssl); }
+ }
+}
+
impl Ssl {
fn new(ctx: &SslCtx) -> Ssl {
let ssl = unsafe { ffi::SSL_new(ctx.ctx) };
@@ -109,10 +112,11 @@ impl Ssl {
ffi::SSL_ERROR_WANT_READ => ErrorWantRead,
ffi::SSL_ERROR_WANT_WRITE => ErrorWantWrite,
ffi::SSL_ERROR_WANT_X509_LOOKUP => ErrorWantX509Lookup,
+ ffi::SSL_ERROR_SYSCALL => ErrorSyscall,
ffi::SSL_ERROR_ZERO_RETURN => ErrorZeroReturn,
ffi::SSL_ERROR_WANT_CONNECT => ErrorWantConnect,
ffi::SSL_ERROR_WANT_ACCEPT => ErrorWantAccept,
- _ => unreachable!()
+ err => fail2!("Unknown error {}", err)
}
}
@@ -129,18 +133,17 @@ impl Ssl {
buf.len() as c_int) as int
}
}
+
+ fn shutdown(&self) -> int {
+ unsafe { ffi::SSL_shutdown(self.ssl) as int }
+ }
}
+// BIOs are freed by SSL_free
struct MemBio {
bio: *ffi::BIO
}
-impl Drop for MemBio {
- fn drop(&mut self) {
- unsafe { ffi::BIO_free(self.bio); }
- }
-}
-
impl MemBio {
fn new() -> MemBio {
let bio = unsafe { ffi::BIO_new(ffi::BIO_s_mem()) };
@@ -240,6 +243,18 @@ impl<S: Stream> SslStream<S> {
self.stream.write(self.buf.slice_to(len));
}
}
+
+ pub fn shutdown(&mut self) {
+ loop {
+ let ret = do self.in_retry_wrapper |ssl| {
+ ssl.ssl.shutdown()
+ };
+
+ if ret != Ok(0) {
+ break;
+ }
+ }
+ }
}
impl<S: Stream> Reader for SslStream<S> {
diff --git a/src/ssl/test.rs b/src/ssl/test.rs
index 7a6dc997..36969e1b 100644
--- a/src/ssl/test.rs
+++ b/src/ssl/test.rs
@@ -1,6 +1,6 @@
extern mod ssl;
-use std::rt::io::{Writer};
+use std::rt::io::{Writer, Reader};
use std::rt::io::net::tcp::TcpStream;
use std::vec;
@@ -13,14 +13,17 @@ fn test_new_ctx() {
#[test]
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()).unwrap();
SslStream::new(SslCtx::new(Sslv23), stream);
}
#[test]
fn test_write() {
- 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()).unwrap();
let mut stream = SslStream::new(SslCtx::new(Sslv23), stream);
stream.write("hello".as_bytes());
stream.flush();
+ stream.write(" there".as_bytes());
+ stream.flush();
+ stream.shutdown();
}