base: Change DCHECK_IS_ON to a macro DCHECK_IS_ON().
[chromium-blink-merge.git] / mojo / services / network / web_socket_impl.cc
blobba09b7eecefbdb9fd777f3557397a0d0a9ac9ffa
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "mojo/services/network/web_socket_impl.h"
7 #include "base/logging.h"
8 #include "base/message_loop/message_loop.h"
9 #include "mojo/common/handle_watcher.h"
10 #include "mojo/services/network/network_context.h"
11 #include "mojo/services/network/public/cpp/web_socket_read_queue.h"
12 #include "mojo/services/network/public/cpp/web_socket_write_queue.h"
13 #include "net/websockets/websocket_channel.h"
14 #include "net/websockets/websocket_errors.h"
15 #include "net/websockets/websocket_event_interface.h"
16 #include "net/websockets/websocket_frame.h" // for WebSocketFrameHeader::OpCode
17 #include "net/websockets/websocket_handshake_request_info.h"
18 #include "net/websockets/websocket_handshake_response_info.h"
19 #include "url/origin.h"
21 namespace mojo {
23 template <>
24 struct TypeConverter<net::WebSocketFrameHeader::OpCode,
25 WebSocket::MessageType> {
26 static net::WebSocketFrameHeader::OpCode Convert(
27 WebSocket::MessageType type) {
28 DCHECK(type == WebSocket::MESSAGE_TYPE_CONTINUATION ||
29 type == WebSocket::MESSAGE_TYPE_TEXT ||
30 type == WebSocket::MESSAGE_TYPE_BINARY);
31 typedef net::WebSocketFrameHeader::OpCode OpCode;
32 // These compile asserts verify that the same underlying values are used for
33 // both types, so we can simply cast between them.
34 COMPILE_ASSERT(static_cast<OpCode>(WebSocket::MESSAGE_TYPE_CONTINUATION) ==
35 net::WebSocketFrameHeader::kOpCodeContinuation,
36 enum_values_must_match_for_opcode_continuation);
37 COMPILE_ASSERT(static_cast<OpCode>(WebSocket::MESSAGE_TYPE_TEXT) ==
38 net::WebSocketFrameHeader::kOpCodeText,
39 enum_values_must_match_for_opcode_text);
40 COMPILE_ASSERT(static_cast<OpCode>(WebSocket::MESSAGE_TYPE_BINARY) ==
41 net::WebSocketFrameHeader::kOpCodeBinary,
42 enum_values_must_match_for_opcode_binary);
43 return static_cast<OpCode>(type);
47 template <>
48 struct TypeConverter<WebSocket::MessageType,
49 net::WebSocketFrameHeader::OpCode> {
50 static WebSocket::MessageType Convert(
51 net::WebSocketFrameHeader::OpCode type) {
52 DCHECK(type == net::WebSocketFrameHeader::kOpCodeContinuation ||
53 type == net::WebSocketFrameHeader::kOpCodeText ||
54 type == net::WebSocketFrameHeader::kOpCodeBinary);
55 return static_cast<WebSocket::MessageType>(type);
59 namespace {
61 typedef net::WebSocketEventInterface::ChannelState ChannelState;
63 struct WebSocketEventHandler : public net::WebSocketEventInterface {
64 public:
65 WebSocketEventHandler(WebSocketClientPtr client)
66 : client_(client.Pass()) {
68 ~WebSocketEventHandler() override {}
70 private:
71 // net::WebSocketEventInterface methods:
72 ChannelState OnAddChannelResponse(bool fail,
73 const std::string& selected_subprotocol,
74 const std::string& extensions) override;
75 ChannelState OnDataFrame(bool fin,
76 WebSocketMessageType type,
77 const std::vector<char>& data) override;
78 ChannelState OnClosingHandshake() override;
79 ChannelState OnFlowControl(int64 quota) override;
80 ChannelState OnDropChannel(bool was_clean,
81 uint16 code,
82 const std::string& reason) override;
83 ChannelState OnFailChannel(const std::string& message) override;
84 ChannelState OnStartOpeningHandshake(
85 scoped_ptr<net::WebSocketHandshakeRequestInfo> request) override;
86 ChannelState OnFinishOpeningHandshake(
87 scoped_ptr<net::WebSocketHandshakeResponseInfo> response) override;
88 ChannelState OnSSLCertificateError(
89 scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
90 const GURL& url,
91 const net::SSLInfo& ssl_info,
92 bool fatal) override;
94 // Called once we've written to |receive_stream_|.
95 void DidWriteToReceiveStream(bool fin,
96 net::WebSocketFrameHeader::OpCode type,
97 uint32_t num_bytes,
98 const char* buffer);
99 WebSocketClientPtr client_;
100 ScopedDataPipeProducerHandle receive_stream_;
101 scoped_ptr<WebSocketWriteQueue> write_queue_;
103 DISALLOW_COPY_AND_ASSIGN(WebSocketEventHandler);
106 ChannelState WebSocketEventHandler::OnAddChannelResponse(
107 bool fail,
108 const std::string& selected_protocol,
109 const std::string& extensions) {
110 DataPipe data_pipe;
111 receive_stream_ = data_pipe.producer_handle.Pass();
112 write_queue_.reset(new WebSocketWriteQueue(receive_stream_.get()));
113 client_->DidConnect(
114 fail, selected_protocol, extensions, data_pipe.consumer_handle.Pass());
115 if (fail)
116 return WebSocketEventInterface::CHANNEL_DELETED;
117 return WebSocketEventInterface::CHANNEL_ALIVE;
120 ChannelState WebSocketEventHandler::OnDataFrame(
121 bool fin,
122 net::WebSocketFrameHeader::OpCode type,
123 const std::vector<char>& data) {
124 uint32_t size = static_cast<uint32_t>(data.size());
125 write_queue_->Write(
126 &data[0], size,
127 base::Bind(&WebSocketEventHandler::DidWriteToReceiveStream,
128 base::Unretained(this),
129 fin, type, size));
130 return WebSocketEventInterface::CHANNEL_ALIVE;
133 ChannelState WebSocketEventHandler::OnClosingHandshake() {
134 return WebSocketEventInterface::CHANNEL_ALIVE;
137 ChannelState WebSocketEventHandler::OnFlowControl(int64 quota) {
138 client_->DidReceiveFlowControl(quota);
139 return WebSocketEventInterface::CHANNEL_ALIVE;
142 ChannelState WebSocketEventHandler::OnDropChannel(bool was_clean,
143 uint16 code,
144 const std::string& reason) {
145 client_->DidClose(was_clean, code, reason);
146 return WebSocketEventInterface::CHANNEL_DELETED;
149 ChannelState WebSocketEventHandler::OnFailChannel(const std::string& message) {
150 client_->DidFail(message);
151 return WebSocketEventInterface::CHANNEL_DELETED;
154 ChannelState WebSocketEventHandler::OnStartOpeningHandshake(
155 scoped_ptr<net::WebSocketHandshakeRequestInfo> request) {
156 return WebSocketEventInterface::CHANNEL_ALIVE;
159 ChannelState WebSocketEventHandler::OnFinishOpeningHandshake(
160 scoped_ptr<net::WebSocketHandshakeResponseInfo> response) {
161 return WebSocketEventInterface::CHANNEL_ALIVE;
164 ChannelState WebSocketEventHandler::OnSSLCertificateError(
165 scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
166 const GURL& url,
167 const net::SSLInfo& ssl_info,
168 bool fatal) {
169 client_->DidFail("SSL Error");
170 return WebSocketEventInterface::CHANNEL_DELETED;
173 void WebSocketEventHandler::DidWriteToReceiveStream(
174 bool fin,
175 net::WebSocketFrameHeader::OpCode type,
176 uint32_t num_bytes,
177 const char* buffer) {
178 client_->DidReceiveData(
179 fin, ConvertTo<WebSocket::MessageType>(type), num_bytes);
182 } // namespace mojo
184 WebSocketImpl::WebSocketImpl(NetworkContext* context) : context_(context) {
187 WebSocketImpl::~WebSocketImpl() {
190 void WebSocketImpl::Connect(const String& url,
191 Array<String> protocols,
192 const String& origin,
193 ScopedDataPipeConsumerHandle send_stream,
194 WebSocketClientPtr client) {
195 DCHECK(!channel_);
196 send_stream_ = send_stream.Pass();
197 read_queue_.reset(new WebSocketReadQueue(send_stream_.get()));
198 scoped_ptr<net::WebSocketEventInterface> event_interface(
199 new WebSocketEventHandler(client.Pass()));
200 channel_.reset(new net::WebSocketChannel(event_interface.Pass(),
201 context_->url_request_context()));
202 channel_->SendAddChannelRequest(GURL(url.get()),
203 protocols.To<std::vector<std::string> >(),
204 url::Origin(origin.get()));
207 void WebSocketImpl::Send(bool fin,
208 WebSocket::MessageType type,
209 uint32_t num_bytes) {
210 DCHECK(channel_);
211 read_queue_->Read(num_bytes,
212 base::Bind(&WebSocketImpl::DidReadFromSendStream,
213 base::Unretained(this),
214 fin, type, num_bytes));
217 void WebSocketImpl::FlowControl(int64_t quota) {
218 DCHECK(channel_);
219 channel_->SendFlowControl(quota);
222 void WebSocketImpl::Close(uint16_t code, const String& reason) {
223 DCHECK(channel_);
224 channel_->StartClosingHandshake(code, reason);
227 void WebSocketImpl::DidReadFromSendStream(bool fin,
228 WebSocket::MessageType type,
229 uint32_t num_bytes,
230 const char* data) {
231 std::vector<char> buffer(num_bytes);
232 memcpy(&buffer[0], data, num_bytes);
233 DCHECK(channel_);
234 channel_->SendFrame(
235 fin, ConvertTo<net::WebSocketFrameHeader::OpCode>(type), buffer);
238 } // namespace mojo