Skip to content

Commit 3a60b54

Browse files
committed
docs and doc tests
1 parent a363b1f commit 3a60b54

File tree

14 files changed

+644
-103
lines changed

14 files changed

+644
-103
lines changed

src/client/builder.rs

Lines changed: 291 additions & 4 deletions
Large diffs are not rendered by default.

src/client/mod.rs

Lines changed: 105 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use ws::receiver::Receiver as ReceiverTrait;
1515
use result::WebSocketResult;
1616
use stream::{AsTcpStream, Stream, Splittable, Shutdown};
1717
use dataframe::DataFrame;
18-
use header::{WebSocketProtocol, WebSocketExtensions, Origin};
18+
use header::{WebSocketProtocol, WebSocketExtensions};
1919
use header::extensions::Extension;
2020

2121
use ws::dataframe::DataFrame as DataFrameable;
@@ -29,27 +29,28 @@ pub use self::builder::{ClientBuilder, Url, ParseError};
2929

3030
/// Represents a WebSocket client, which can send and receive messages/data frames.
3131
///
32-
/// `D` is the data frame type, `S` is the type implementing `Sender<D>` and `R`
33-
/// is the type implementing `Receiver<D>`.
32+
/// The client just wraps around a `Stream` (which is something that can be read from
33+
/// and written to) and handles the websocket protocol. TCP or SSL over TCP is common,
34+
/// but any stream can be used.
3435
///
35-
/// For most cases, the data frame type will be `dataframe::DataFrame`, the Sender
36-
/// type will be `client::Sender<stream::WebSocketStream>` and the receiver type
37-
/// will be `client::Receiver<stream::WebSocketStream>`.
38-
///
39-
/// A `Client` can be split into a `Sender` and a `Receiver` which can then be moved
36+
/// A `Client` can also be split into a `Reader` and a `Writer` which can then be moved
4037
/// to different threads, often using a send loop and receiver loop concurrently,
4138
/// as shown in the client example in `examples/client.rs`.
39+
/// This is only possible for streams that implement the `Splittable` trait, which
40+
/// currently is only TCP streams. (it is unsafe to duplicate an SSL stream)
4241
///
43-
///#Connecting to a Server
42+
///# Connecting to a Server
4443
///
4544
///```no_run
4645
///extern crate websocket;
4746
///# fn main() {
4847
///
4948
///use websocket::{ClientBuilder, Message};
5049
///
51-
///let mut client = ClientBuilder::new("ws://127.0.0.1:1234").unwrap()
52-
/// .connect(None).unwrap();
50+
///let mut client = ClientBuilder::new("ws://127.0.0.1:1234")
51+
/// .unwrap()
52+
/// .connect_insecure()
53+
/// .unwrap();
5354
///
5455
///let message = Message::text("Hello, World!");
5556
///client.send_message(&message).unwrap(); // Send message
@@ -87,17 +88,20 @@ impl<S> Client<S>
8788
self.stream.get_ref().as_tcp().shutdown(Shutdown::Both)
8889
}
8990

90-
/// See `TcpStream.peer_addr()`.
91+
/// See [`TcpStream::peer_addr`]
92+
/// (https://doc.rust-lang.org/std/net/struct.TcpStream.html#method.peer_addr).
9193
pub fn peer_addr(&self) -> IoResult<SocketAddr> {
9294
self.stream.get_ref().as_tcp().peer_addr()
9395
}
9496

95-
/// See `TcpStream.local_addr()`.
97+
/// See [`TcpStream::local_addr`]
98+
/// (https://doc.rust-lang.org/std/net/struct.TcpStream.html#method.local_addr).
9699
pub fn local_addr(&self) -> IoResult<SocketAddr> {
97100
self.stream.get_ref().as_tcp().local_addr()
98101
}
99102

100-
/// See `TcpStream.set_nodelay()`.
103+
/// See [`TcpStream::set_nodelay`]
104+
/// (https://doc.rust-lang.org/std/net/struct.TcpStream.html#method.set_nodelay).
101105
pub fn set_nodelay(&mut self, nodelay: bool) -> IoResult<()> {
102106
self.stream.get_ref().as_tcp().set_nodelay(nodelay)
103107
}
@@ -115,6 +119,7 @@ impl<S> Client<S>
115119
/// **without sending any handshake** this is meant to only be used with
116120
/// a stream that has a websocket connection already set up.
117121
/// If in doubt, don't use this!
122+
#[doc(hidden)]
118123
pub fn unchecked(stream: BufReader<S>, headers: Headers) -> Self {
119124
Client {
120125
headers: headers,
@@ -159,40 +164,122 @@ impl<S> Client<S>
159164
self.receiver.recv_message(&mut self.stream)
160165
}
161166

167+
/// Access the headers that were sent in the server's handshake response.
168+
/// This is a catch all for headers other than protocols and extensions.
162169
pub fn headers(&self) -> &Headers {
163170
&self.headers
164171
}
165172

173+
/// **If you supplied a protocol, you must check that it was accepted by
174+
/// the server** using this function.
175+
/// This is not done automatically because the terms of accepting a protocol
176+
/// can get complicated, especially if some protocols depend on others, etc.
177+
///
178+
/// ```rust,no_run
179+
/// # use websocket::ClientBuilder;
180+
/// let mut client = ClientBuilder::new("wss://test.fysh.in").unwrap()
181+
/// .add_protocol("xmpp")
182+
/// .connect_insecure()
183+
/// .unwrap();
184+
///
185+
/// // be sure to check the protocol is there!
186+
/// assert!(client.protocols().iter().any(|p| p as &str == "xmpp"));
187+
/// ```
166188
pub fn protocols(&self) -> &[String] {
167189
self.headers
168190
.get::<WebSocketProtocol>()
169191
.map(|p| p.0.as_slice())
170192
.unwrap_or(&[])
171193
}
172194

195+
/// If you supplied a protocol, be sure to check if it was accepted by the
196+
/// server here. Since no extensions are implemented out of the box yet, using
197+
/// one will require its own implementation.
173198
pub fn extensions(&self) -> &[Extension] {
174199
self.headers
175200
.get::<WebSocketExtensions>()
176201
.map(|e| e.0.as_slice())
177202
.unwrap_or(&[])
178203
}
179204

180-
pub fn origin(&self) -> Option<&str> {
181-
self.headers.get::<Origin>().map(|o| &o.0 as &str)
182-
}
183-
205+
/// Get a reference to the stream.
206+
/// Useful to be able to set options on the stream.
207+
///
208+
/// ```rust,no_run
209+
/// # use websocket::ClientBuilder;
210+
/// let mut client = ClientBuilder::new("ws://double.down").unwrap()
211+
/// .connect_insecure()
212+
/// .unwrap();
213+
///
214+
/// client.stream_ref().set_ttl(60).unwrap();
215+
/// ```
184216
pub fn stream_ref(&self) -> &S {
185217
self.stream.get_ref()
186218
}
187219

220+
/// Get a handle to the writable portion of this stream.
221+
/// This can be used to write custom extensions.
222+
///
223+
/// ```rust,no_run
224+
/// # use websocket::ClientBuilder;
225+
/// use websocket::Message;
226+
/// use websocket::ws::sender::Sender as SenderTrait;
227+
/// use websocket::sender::Sender;
228+
///
229+
/// let mut client = ClientBuilder::new("ws://the.room").unwrap()
230+
/// .connect_insecure()
231+
/// .unwrap();
232+
///
233+
/// let message = Message::text("Oh hi, Mark.");
234+
/// let mut sender = Sender::new(true);
235+
/// let mut buf = Vec::new();
236+
///
237+
/// sender.send_message(&mut buf, &message);
238+
///
239+
/// /* transform buf somehow */
240+
///
241+
/// client.writer_mut().write_all(&buf);
242+
/// ```
188243
pub fn writer_mut(&mut self) -> &mut Write {
189244
self.stream.get_mut()
190245
}
191246

247+
/// Get a handle to the readable portion of this stream.
248+
/// This can be used to transform raw bytes before they
249+
/// are read in.
250+
///
251+
/// ```rust,no_run
252+
/// # use websocket::ClientBuilder;
253+
/// use std::io::Cursor;
254+
/// use websocket::Message;
255+
/// use websocket::ws::receiver::Receiver as ReceiverTrait;
256+
/// use websocket::receiver::Receiver;
257+
///
258+
/// let mut client = ClientBuilder::new("ws://the.room").unwrap()
259+
/// .connect_insecure()
260+
/// .unwrap();
261+
///
262+
/// let mut receiver = Receiver::new(false);
263+
/// let mut buf = Vec::new();
264+
///
265+
/// client.reader_mut().read_to_end(&mut buf);
266+
///
267+
/// /* transform buf somehow */
268+
///
269+
/// let mut buf_reader = Cursor::new(&mut buf);
270+
/// let message: Message = receiver.recv_message(&mut buf_reader).unwrap();
271+
/// ```
192272
pub fn reader_mut(&mut self) -> &mut Read {
193273
&mut self.stream
194274
}
195275

276+
/// Deconstruct the client into its underlying stream and
277+
/// maybe some of the buffer that was already read from the stream.
278+
/// The client uses a buffered reader to read in messages, so some
279+
/// bytes might already be read from the stream when this is called,
280+
/// these buffered bytes are returned in the form
281+
///
282+
/// `(byte_buffer: Vec<u8>, buffer_capacity: usize, buffer_position: usize)`
196283
pub fn into_stream(self) -> (S, Option<(Vec<u8>, usize, usize)>) {
197284
let (stream, buf, pos, cap) = self.stream.into_parts();
198285
(stream, Some((buf, pos, cap)))

src/header/extensions.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use result::{WebSocketResult, WebSocketError};
1010

1111
const INVALID_EXTENSION: &'static str = "Invalid Sec-WebSocket-Extensions extension name";
1212

13+
// TODO: check if extension name is valid according to spec
14+
1315
/// Represents a Sec-WebSocket-Extensions header
1416
#[derive(PartialEq, Clone, Debug)]
1517
pub struct WebSocketExtensions(pub Vec<Extension>);

src/header/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub use self::protocol::WebSocketProtocol;
99
pub use self::version::WebSocketVersion;
1010
pub use self::extensions::WebSocketExtensions;
1111
pub use self::origin::Origin;
12-
pub use hyper::header::Headers;
12+
pub use hyper::header::*;
1313

1414
mod accept;
1515
mod key;

src/header/protocol.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use hyper;
44
use std::fmt;
55
use std::ops::Deref;
66

7+
// TODO: only allow valid protocol names to be added
8+
79
/// Represents a Sec-WebSocket-Protocol header
810
#[derive(PartialEq, Clone, Debug)]
911
pub struct WebSocketProtocol(pub Vec<String>);

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
//! level. Their usage is explained in the module documentation.
3939
extern crate hyper;
4040
extern crate unicase;
41-
extern crate url;
41+
pub extern crate url;
4242
extern crate rustc_serialize as serialize;
4343
extern crate rand;
4444
extern crate byteorder;

src/receiver.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@ use ws::receiver::{MessageIterator, DataFrameIterator};
1414
use stream::{AsTcpStream, Stream};
1515
pub use stream::Shutdown;
1616

17+
/// This reader bundles an existing stream with a parsing algorithm.
18+
/// It is used by the client in its `.split()` function as the reading component.
1719
pub struct Reader<R>
1820
where R: Read
1921
{
22+
/// the stream to be read from
2023
pub stream: BufReader<R>,
24+
/// the parser to parse bytes into messages
2125
pub receiver: Receiver,
2226
}
2327

@@ -42,6 +46,8 @@ impl<R> Reader<R>
4246
self.receiver.recv_message(&mut self.stream)
4347
}
4448

49+
/// An iterator over incoming messsages.
50+
/// This iterator will block until new messages arrive and will never halt.
4551
pub fn incoming_messages<'a, M, D>(&'a mut self,)
4652
-> MessageIterator<'a, Receiver, D, M, BufReader<R>>
4753
where M: ws::Message<'a, D>,

src/sender.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,14 @@ use ws;
99
use ws::sender::Sender as SenderTrait;
1010
pub use stream::Shutdown;
1111

12+
/// A writer that bundles a stream with a serializer to send the messages.
13+
/// This is used in the client's `.split()` function as the writing component.
14+
///
15+
/// It can also be useful to use a websocket connection without a handshake.
1216
pub struct Writer<W> {
17+
/// The stream that websocket messages will be written to
1318
pub stream: W,
19+
/// The serializer that will be used to serialize the messages
1420
pub sender: Sender,
1521
}
1622

src/server/mod.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,31 @@ pub use self::upgrade::{Request, HyperIntoWsError};
1010

1111
pub mod upgrade;
1212

13+
/// When a sever tries to accept a connection many things can go wrong.
14+
///
15+
/// This struct is all the information that is recovered from a failed
16+
/// websocket handshake, in case one wants to use the connection for something
17+
/// else (such as HTTP).
1318
pub struct InvalidConnection<S>
1419
where S: Stream
1520
{
21+
/// if the stream was successfully setup it will be included here
22+
/// on a failed connection.
1623
pub stream: Option<S>,
24+
/// the parsed request. **This is a normal HTTP request** meaning you can
25+
/// simply run this server and handle both HTTP and Websocket connections.
26+
/// If you already have a server you want to use, checkout the
27+
/// `server::upgrade` module to integrate this crate with your server.
1728
pub parsed: Option<Request>,
29+
/// the buffered data that was already taken from the stream
1830
pub buffer: Option<Buffer>,
31+
/// the cause of the failed websocket connection setup
1932
pub error: HyperIntoWsError,
2033
}
2134

35+
/// Either the stream was established and it sent a websocket handshake
36+
/// which represents the `Ok` variant, or there was an error (this is the
37+
/// `Err` variant).
2238
pub type AcceptResult<S> = Result<WsUpgrade<S>, InvalidConnection<S>>;
2339

2440
/// Marker struct for a struct not being secure
@@ -39,7 +55,7 @@ impl OptionalSslAcceptor for SslAcceptor {}
3955
/// This is a convenient way to implement WebSocket servers, however
4056
/// it is possible to use any sendable Reader and Writer to obtain
4157
/// a WebSocketClient, so if needed, an alternative server implementation can be used.
42-
///#Non-secure Servers
58+
///# Non-secure Servers
4359
///
4460
/// ```no_run
4561
///extern crate websocket;
@@ -63,7 +79,7 @@ impl OptionalSslAcceptor for SslAcceptor {}
6379
/// # }
6480
/// ```
6581
///
66-
///#Secure Servers
82+
///# Secure Servers
6783
/// ```no_run
6884
///extern crate websocket;
6985
///extern crate openssl;
@@ -106,10 +122,21 @@ impl OptionalSslAcceptor for SslAcceptor {}
106122
///}
107123
/// # }
108124
/// ```
125+
///
126+
/// # A Hyper Server
127+
/// This crates comes with hyper integration out of the box, you can create a hyper
128+
/// server and serve websocket and HTTP **on the same port!**
129+
/// check out the docs over at `websocket::server::upgrade::from_hyper` for an example.
130+
///
131+
/// # A Custom Server
132+
/// So you don't want to use any of our server implementations? That's O.K.
133+
/// All it takes is implementing the `IntoWs` trait for your server's streams,
134+
/// then calling `.into_ws()` on them.
135+
/// check out the docs over at `websocket::server::upgrade` for more.
109136
pub struct Server<S>
110137
where S: OptionalSslAcceptor
111138
{
112-
pub listener: TcpListener,
139+
listener: TcpListener,
113140
ssl_acceptor: S,
114141
}
115142

0 commit comments

Comments
 (0)