Skip to content

Commit 5c534de

Browse files
poidlMichael Eden
authored andcommitted
move set_nonblocking() to server with OptionalSslAcceptor (#121)
* move set_nonblocking() to server with OptionalSslAcceptor * add test for set_nonblocking() * add docs
1 parent 7435863 commit 5c534de

File tree

1 file changed

+74
-8
lines changed

1 file changed

+74
-8
lines changed

src/server/mod.rs

Lines changed: 74 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,47 @@ impl<S> Server<S>
156156
ssl_acceptor: self.ssl_acceptor.clone(),
157157
})
158158
}
159+
160+
/// Changes whether the Server is in nonblocking mode.
161+
///
162+
/// If it is in nonblocking mode, accept() will return an error instead of blocking when there
163+
/// are no incoming connections.
164+
///
165+
///# Examples
166+
///```no_run
167+
/// # extern crate websocket;
168+
/// # use websocket::Server;
169+
/// # fn main() {
170+
/// // Suppose we have to work in a single thread, but want to
171+
/// // accomplish two unrelated things:
172+
/// // (1) Once in a while we want to check if anybody tried to connect to
173+
/// // our websocket server, and if so, handle the TcpStream.
174+
/// // (2) In between we need to something else, possibly unrelated to networking.
175+
///
176+
/// let mut server = Server::bind("127.0.0.1:0").unwrap();
177+
///
178+
/// // Set the server to non-blocking.
179+
/// server.set_nonblocking(true);
180+
///
181+
/// for i in 1..3 {
182+
/// let result = match server.accept() {
183+
/// Ok(wsupgrade) => {
184+
/// // Do something with the established TcpStream.
185+
/// }
186+
/// _ => {
187+
/// // Nobody tried to connect, move on.
188+
/// }
189+
/// };
190+
/// // Perform another task. Because we have a non-blocking server,
191+
/// // this will execute independent of whether someone tried to
192+
/// // establish a connection.
193+
/// let two = 1+1;
194+
/// }
195+
/// # }
196+
///```
197+
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
198+
self.listener.set_nonblocking(nonblocking)
199+
}
159200
}
160201

161202
#[cfg(feature="ssl")]
@@ -208,14 +249,6 @@ impl Server<SslAcceptor> {
208249
}
209250
}
210251
}
211-
212-
/// Changes whether the Server is in nonblocking mode.
213-
///
214-
/// If it is in nonblocking mode, accept() will return an error instead of blocking when there
215-
/// are no incoming connections.
216-
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
217-
self.listener.set_nonblocking(nonblocking)
218-
}
219252
}
220253

221254
#[cfg(feature="ssl")]
@@ -271,3 +304,36 @@ impl Iterator for Server<NoSslAcceptor> {
271304
Some(self.accept())
272305
}
273306
}
307+
308+
mod tests {
309+
#[test]
310+
// test the set_nonblocking() method for Server<NoSslAcceptor>.
311+
// Some of this is copied from
312+
// https://doc.rust-lang.org/src/std/net/tcp.rs.html#1413
313+
fn set_nonblocking() {
314+
315+
use super::*;
316+
317+
// Test unsecure server
318+
319+
let mut server = Server::bind("127.0.0.1:0").unwrap();
320+
321+
// Note that if set_nonblocking() doesn't work, but the following
322+
// fails to panic for some reason, then the .accept() method below
323+
// will block indefinitely.
324+
server.set_nonblocking(true).unwrap();
325+
326+
let result = server.accept();
327+
match result {
328+
// nobody tried to establish a connection, so we expect an error
329+
Ok(_) => panic!("expected error"),
330+
Err(e) => {
331+
match e.error {
332+
HyperIntoWsError::Io(ref e) if e.kind() == io::ErrorKind::WouldBlock => {}
333+
_ => panic!("unexpected error {}"),
334+
}
335+
}
336+
}
337+
338+
}
339+
}

0 commit comments

Comments
 (0)