aboutsummaryrefslogtreecommitdiff
path: root/openssl/src/ssl/tests.rs
diff options
context:
space:
mode:
authorJamie Turner <[email protected]>2015-09-19 20:50:06 -0700
committerJamie Turner <[email protected]>2015-10-20 23:14:26 -0700
commitc37767df8fc1775858cd573cbe4d5e3a17fbd370 (patch)
treea80fcebc4891737bc833a51b4cf5034dcb63ab6f /openssl/src/ssl/tests.rs
parentMerge pull request #290 from jimmycuadra/master (diff)
downloadrust-openssl-c37767df8fc1775858cd573cbe4d5e3a17fbd370.tar.xz
rust-openssl-c37767df8fc1775858cd573cbe4d5e3a17fbd370.zip
Nonblocking streams support.
Diffstat (limited to 'openssl/src/ssl/tests.rs')
-rw-r--r--openssl/src/ssl/tests.rs132
1 files changed, 132 insertions, 0 deletions
diff --git a/openssl/src/ssl/tests.rs b/openssl/src/ssl/tests.rs
index 033a3b86..8335bc53 100644
--- a/openssl/src/ssl/tests.rs
+++ b/openssl/src/ssl/tests.rs
@@ -819,3 +819,135 @@ fn test_sslv2_connect_failure() {
let (_s, tcp) = Server::new_tcp(&["-no_ssl2", "-www"]);
SslStream::connect_generic(&SslContext::new(Sslv2).unwrap(), tcp).err().unwrap();
}
+
+#[cfg(target_os = "linux")]
+mod nonblocking_tests {
+ extern crate nix;
+
+ use std::io::Write;
+ use std::net::TcpStream;
+ use std::os::unix::io::AsRawFd;
+
+ use super::Server;
+ use self::nix::sys::epoll;
+ use self::nix::fcntl;
+ use ssl;
+ use ssl::error::NonblockingSslError;
+ use ssl::SslMethod;
+ use ssl::SslMethod::Sslv23;
+ use ssl::{SslContext, NonblockingSslStream};
+
+ fn wait_io(stream: &NonblockingSslStream<TcpStream>, read: bool, timeout_ms: isize) -> bool {
+ let fd = stream.as_raw_fd();
+ let ep = epoll::epoll_create().unwrap();
+ let event = if read {
+ epoll::EpollEvent {
+ events: epoll::EPOLLIN | epoll::EPOLLERR,
+ data: 0,
+ }
+ } else {
+ epoll::EpollEvent {
+ events: epoll::EPOLLOUT,
+ data: 0,
+ }
+ };
+ epoll::epoll_ctl(ep, epoll::EpollOp::EpollCtlAdd, fd, &event).unwrap();
+ let mut events = [event];
+ let count = epoll::epoll_wait(ep, &mut events, timeout_ms).unwrap();
+ epoll::epoll_ctl(ep, epoll::EpollOp::EpollCtlDel, fd, &event).unwrap();
+ assert!(count <= 1);
+ count == 1
+ }
+
+ fn make_nonblocking(stream: &TcpStream) {
+ let fd = stream.as_raw_fd();
+ fcntl::fcntl(fd, fcntl::FcntlArg::F_SETFL(fcntl::O_NONBLOCK)).unwrap();
+ }
+
+ #[test]
+ fn test_write_nonblocking() {
+ let (_s, stream) = Server::new();
+ make_nonblocking(&stream);
+ let mut stream = NonblockingSslStream::connect(&SslContext::new(Sslv23).unwrap(), stream).unwrap();
+
+ let mut iterations = 0;
+ loop {
+ iterations += 1;
+ if iterations > 7 {
+ // Probably a safe assumption for the foreseeable future of openssl.
+ panic!("Too many read/write round trips in handshake!!");
+ }
+ let result = stream.write("hello".as_bytes());
+ match result {
+ Ok(_) => {
+ break;
+ },
+ Err(NonblockingSslError::WantRead) => {
+ assert!(wait_io(&stream, true, 1000));
+ },
+ Err(NonblockingSslError::WantWrite) => {
+ assert!(wait_io(&stream, false, 1000));
+ },
+ Err(other) => {
+ panic!("Unexpected SSL Error: {:?}", other);
+ },
+ }
+ }
+
+ // Second write should succeed immediately--plenty of space in kernel buffer,
+ // and handshake just completed.
+ stream.write(" there".as_bytes()).unwrap();
+ }
+
+ #[test]
+ fn test_read_nonblocking() {
+ let (_s, stream) = Server::new();
+ make_nonblocking(&stream);
+ let mut stream = NonblockingSslStream::connect(&SslContext::new(Sslv23).unwrap(), stream).unwrap();
+
+ let mut iterations = 0;
+ loop {
+ iterations += 1;
+ if iterations > 7 {
+ // Probably a safe assumption for the foreseeable future of openssl.
+ panic!("Too many read/write round trips in handshake!!");
+ }
+ let result = stream.write("GET /\r\n\r\n".as_bytes());
+ match result {
+ Ok(n) => {
+ assert_eq!(n, 9);
+ break;
+ },
+ Err(NonblockingSslError::WantRead) => {
+ assert!(wait_io(&stream, true, 1000));
+ },
+ Err(NonblockingSslError::WantWrite) => {
+ assert!(wait_io(&stream, false, 1000));
+ },
+ Err(other) => {
+ panic!("Unexpected SSL Error: {:?}", other);
+ },
+ }
+ }
+ let mut input_buffer = [0u8; 1500];
+ let result = stream.read(&mut input_buffer);
+ let bytes_read = match result {
+ Ok(n) => {
+ // This branch is unlikely, but on an overloaded VM with
+ // unlucky context switching, the response could actually
+ // be in the receive buffer before we issue the read() syscall...
+ n
+ },
+ Err(NonblockingSslError::WantRead) => {
+ assert!(wait_io(&stream, true, 3000));
+ // Second read should return application data.
+ stream.read(&mut input_buffer).unwrap()
+ },
+ Err(other) => {
+ panic!("Unexpected SSL Error: {:?}", other);
+ },
+ };
+ assert!(bytes_read >= 5);
+ assert_eq!(&input_buffer[..5], b"HTTP/");
+ }
+}