1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//! Structs for WebSocket responses
use std::option::Option;
use std::io::{Read, Write};

use hyper::status::StatusCode;
use hyper::buffer::BufReader;
use hyper::version::HttpVersion;
use hyper::header::Headers;
use hyper::header::{Connection, ConnectionOption};
use hyper::header::{Upgrade, Protocol, ProtocolName};
use hyper::http::h1::parse_response;

use unicase::UniCase;

use header::{WebSocketAccept, WebSocketProtocol, WebSocketExtensions};

use client::{Client, Request, Sender, Receiver};
use result::{WebSocketResult, WebSocketError};
use dataframe::DataFrame;
use ws::dataframe::DataFrame as DataFrameable;
use ws;

/// Represents a WebSocket response.
pub struct Response<R: Read, W: Write> {
	/// The status of the response
	pub status: StatusCode,
	/// The headers contained in this response
	pub headers: Headers,
	/// The HTTP version of this response
	pub version: HttpVersion,

	request: Request<R, W>
}

unsafe impl<R, W> Send for Response<R, W> where R: Read + Send, W: Write + Send { }

impl<R: Read, W: Write> Response<R, W> {
	/// Reads a Response off the stream associated with a Request.
	///
	/// This is called by Request.send(), and does not need to be called by the user.
	pub fn read(mut request: Request<R, W>) -> WebSocketResult<Response<R, W>> {
		let (status, version, headers) = {
			let reader = request.get_mut_reader();

			let response = try!(parse_response(reader));

			let status = StatusCode::from_u16(response.subject.0);
			(status, response.version, response.headers)
		};

		Ok(Response {
			status: status,
			headers: headers,
			version: version,
			request: request
		})
	}

	/// Short-cut to obtain the WebSocketAccept value.
	pub fn accept(&self) -> Option<&WebSocketAccept> {
		self.headers.get()
	}
	/// Short-cut to obtain the WebSocketProtocol value.
	pub fn protocol(&self) -> Option<&WebSocketProtocol> {
		self.headers.get()
	}
	/// Short-cut to obtain the WebSocketExtensions value.
	pub fn extensions(&self) -> Option<&WebSocketExtensions> {
		self.headers.get()
	}
		/// Returns a reference to the inner Reader.
	pub fn get_reader(&self) -> &BufReader<R> {
		self.request.get_reader()
	}
	/// Returns a reference to the inner Writer.
	pub fn get_writer(&self) -> &W {
		self.request.get_writer()
	}
	/// Returns a mutable reference to the inner Reader.
	pub fn get_mut_reader(&mut self) -> &mut BufReader<R> {
		self.request.get_mut_reader()
	}
	/// Returns a mutable reference to the inner Writer.
	pub fn get_mut_writer(&mut self) -> &mut W {
		self.request.get_mut_writer()
	}
	/// Returns a reference to the request associated with this response.
	pub fn get_request(&self) -> &Request<R, W> {
		&self.request
	}
	/// Return the inner Reader and Writer.
	pub fn into_inner(self) -> (BufReader<R>, W) {
		self.request.into_inner()
	}

	/// Check if this response constitutes a successful handshake.
	pub fn validate(&self) -> WebSocketResult<()> {
		if self.status != StatusCode::SwitchingProtocols {
			return Err(WebSocketError::ResponseError("Status code must be Switching Protocols"));
		}
		let key = try!(self.request.key().ok_or(
			WebSocketError::RequestError("Request Sec-WebSocket-Key was invalid")
		));
		if self.accept() != Some(&(WebSocketAccept::new(key))) {
			return Err(WebSocketError::ResponseError("Sec-WebSocket-Accept is invalid"));
		}
		if self.headers.get() != Some(&(Upgrade(vec![Protocol{
			name: ProtocolName::WebSocket,
			version: None
		}]))) {
			return Err(WebSocketError::ResponseError("Upgrade field must be WebSocket"));
		}
		if self.headers.get() != Some(&(Connection(vec![ConnectionOption::ConnectionHeader(UniCase("Upgrade".to_string()))]))) {
			return Err(WebSocketError::ResponseError("Connection field must be 'Upgrade'"));
		}
		Ok(())
	}

	/// Consume this response and return a Client ready to transmit/receive data frames
	/// using the data frame type D, Sender B and Receiver C.
	///
	/// Does not check if the response was valid. Use `validate()` to ensure that the response constitutes a successful handshake.
	pub fn begin_with<D, B, C>(self, sender: B, receiver: C) -> Client<D, B, C>
	where B: ws::Sender, C: ws::Receiver<D>, D: DataFrameable {
		Client::new(sender, receiver)
	}
	/// Consume this response and return a Client ready to transmit/receive data frames.
	///
	/// Does not check if the response was valid. Use `validate()` to ensure that the response constitutes a successful handshake.
	pub fn begin(self) -> Client<DataFrame, Sender<W>, Receiver<R>> {
		let (reader, writer) = self.into_inner();
		let sender = Sender::new(writer, true);
		let receiver = Receiver::new(reader.into_inner(), false);
		Client::new(sender, receiver)
	}
}