| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "mojo/services/network/http_connection_impl.h" | 5 #include "mojo/services/network/http_connection_impl.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 #include <utility> |
| 8 | 9 |
| 9 #include "base/bind.h" | 10 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
| 11 #include "base/callback.h" | 12 #include "base/callback.h" |
| 12 #include "base/logging.h" | 13 #include "base/logging.h" |
| 13 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
| 14 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
| 15 #include "mojo/message_pump/handle_watcher.h" | 16 #include "mojo/message_pump/handle_watcher.h" |
| 16 #include "mojo/public/cpp/bindings/type_converter.h" | 17 #include "mojo/public/cpp/bindings/type_converter.h" |
| 17 #include "mojo/public/cpp/system/data_pipe.h" | 18 #include "mojo/public/cpp/system/data_pipe.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 35 public: | 36 public: |
| 36 using CompletionCallback = | 37 using CompletionCallback = |
| 37 base::Callback<void(SimpleDataPipeReader*, scoped_ptr<std::string>)>; | 38 base::Callback<void(SimpleDataPipeReader*, scoped_ptr<std::string>)>; |
| 38 | 39 |
| 39 SimpleDataPipeReader() {} | 40 SimpleDataPipeReader() {} |
| 40 ~SimpleDataPipeReader() {} | 41 ~SimpleDataPipeReader() {} |
| 41 | 42 |
| 42 void Start(ScopedDataPipeConsumerHandle consumer, | 43 void Start(ScopedDataPipeConsumerHandle consumer, |
| 43 const CompletionCallback& completion_callback) { | 44 const CompletionCallback& completion_callback) { |
| 44 DCHECK(consumer.is_valid() && !consumer_.is_valid()); | 45 DCHECK(consumer.is_valid() && !consumer_.is_valid()); |
| 45 consumer_ = consumer.Pass(); | 46 consumer_ = std::move(consumer); |
| 46 completion_callback_ = completion_callback; | 47 completion_callback_ = completion_callback; |
| 47 buffer_.reset(new std::string); | 48 buffer_.reset(new std::string); |
| 48 ReadMore(); | 49 ReadMore(); |
| 49 } | 50 } |
| 50 | 51 |
| 51 private: | 52 private: |
| 52 void ReadMore() { | 53 void ReadMore() { |
| 53 const void* buf; | 54 const void* buf; |
| 54 uint32_t buf_size; | 55 uint32_t buf_size; |
| 55 MojoResult rv = BeginReadDataRaw(consumer_.get(), &buf, &buf_size, | 56 MojoResult rv = BeginReadDataRaw(consumer_.get(), &buf, &buf_size, |
| 56 MOJO_READ_DATA_FLAG_NONE); | 57 MOJO_READ_DATA_FLAG_NONE); |
| 57 if (rv == MOJO_RESULT_OK) { | 58 if (rv == MOJO_RESULT_OK) { |
| 58 buffer_->append(static_cast<const char*>(buf), buf_size); | 59 buffer_->append(static_cast<const char*>(buf), buf_size); |
| 59 EndReadDataRaw(consumer_.get(), buf_size); | 60 EndReadDataRaw(consumer_.get(), buf_size); |
| 60 WaitToReadMore(); | 61 WaitToReadMore(); |
| 61 } else if (rv == MOJO_RESULT_SHOULD_WAIT) { | 62 } else if (rv == MOJO_RESULT_SHOULD_WAIT) { |
| 62 WaitToReadMore(); | 63 WaitToReadMore(); |
| 63 } else if (rv == MOJO_RESULT_FAILED_PRECONDITION) { | 64 } else if (rv == MOJO_RESULT_FAILED_PRECONDITION) { |
| 64 // We reached end-of-file. | 65 // We reached end-of-file. |
| 65 completion_callback_.Run(this, buffer_.Pass()); | 66 completion_callback_.Run(this, std::move(buffer_)); |
| 66 // Note: This object may have been destroyed in the callback. | 67 // Note: This object may have been destroyed in the callback. |
| 67 } else { | 68 } else { |
| 68 CHECK(false); | 69 CHECK(false); |
| 69 } | 70 } |
| 70 } | 71 } |
| 71 | 72 |
| 72 void WaitToReadMore() { | 73 void WaitToReadMore() { |
| 73 watcher_.Start(consumer_.get(), MOJO_HANDLE_SIGNAL_READABLE, | 74 watcher_.Start(consumer_.get(), MOJO_HANDLE_SIGNAL_READABLE, |
| 74 MOJO_DEADLINE_INDEFINITE, | 75 MOJO_DEADLINE_INDEFINITE, |
| 75 base::Bind(&SimpleDataPipeReader::OnHandleReady, | 76 base::Bind(&SimpleDataPipeReader::OnHandleReady, |
| (...skipping 11 matching lines...) Expand all Loading... |
| 87 }; | 88 }; |
| 88 | 89 |
| 89 class HttpConnectionImpl::WebSocketImpl : public WebSocket { | 90 class HttpConnectionImpl::WebSocketImpl : public WebSocket { |
| 90 public: | 91 public: |
| 91 // |connection| must outlive this object. | 92 // |connection| must outlive this object. |
| 92 WebSocketImpl(HttpConnectionImpl* connection, | 93 WebSocketImpl(HttpConnectionImpl* connection, |
| 93 InterfaceRequest<WebSocket> request, | 94 InterfaceRequest<WebSocket> request, |
| 94 ScopedDataPipeConsumerHandle send_stream, | 95 ScopedDataPipeConsumerHandle send_stream, |
| 95 WebSocketClientPtr client) | 96 WebSocketClientPtr client) |
| 96 : connection_(connection), | 97 : connection_(connection), |
| 97 binding_(this, request.Pass()), | 98 binding_(this, std::move(request)), |
| 98 client_(client.Pass()), | 99 client_(std::move(client)), |
| 99 send_stream_(send_stream.Pass()), | 100 send_stream_(std::move(send_stream)), |
| 100 read_send_stream_(new WebSocketReadQueue(send_stream_.get())), | 101 read_send_stream_(new WebSocketReadQueue(send_stream_.get())), |
| 101 pending_send_count_(0) { | 102 pending_send_count_(0) { |
| 102 DCHECK(binding_.is_bound()); | 103 DCHECK(binding_.is_bound()); |
| 103 DCHECK(client_); | 104 DCHECK(client_); |
| 104 DCHECK(send_stream_.is_valid()); | 105 DCHECK(send_stream_.is_valid()); |
| 105 | 106 |
| 106 binding_.set_connection_error_handler([this]() { Close(); }); | 107 binding_.set_connection_error_handler([this]() { Close(); }); |
| 107 client_.set_connection_error_handler([this]() { Close(); }); | 108 client_.set_connection_error_handler([this]() { Close(); }); |
| 108 | 109 |
| 109 DataPipe data_pipe; | 110 DataPipe data_pipe; |
| 110 receive_stream_ = data_pipe.producer_handle.Pass(); | 111 receive_stream_ = std::move(data_pipe.producer_handle); |
| 111 write_receive_stream_.reset(new WebSocketWriteQueue(receive_stream_.get())); | 112 write_receive_stream_.reset(new WebSocketWriteQueue(receive_stream_.get())); |
| 112 | 113 |
| 113 client_->DidConnect("", "", data_pipe.consumer_handle.Pass()); | 114 client_->DidConnect("", "", std::move(data_pipe.consumer_handle)); |
| 114 } | 115 } |
| 115 | 116 |
| 116 ~WebSocketImpl() override {} | 117 ~WebSocketImpl() override {} |
| 117 | 118 |
| 118 void Close() { | 119 void Close() { |
| 119 DCHECK(!IsClosing()); | 120 DCHECK(!IsClosing()); |
| 120 | 121 |
| 121 binding_.Close(); | 122 binding_.Close(); |
| 122 client_.reset(); | 123 client_.reset(); |
| 123 | 124 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 static HttpRequestPtr Convert(const net::HttpServerRequestInfo& obj) { | 225 static HttpRequestPtr Convert(const net::HttpServerRequestInfo& obj) { |
| 225 HttpRequestPtr request(HttpRequest::New()); | 226 HttpRequestPtr request(HttpRequest::New()); |
| 226 request->method = obj.method; | 227 request->method = obj.method; |
| 227 request->url = obj.path; | 228 request->url = obj.path; |
| 228 request->headers.resize(obj.headers.size()); | 229 request->headers.resize(obj.headers.size()); |
| 229 size_t index = 0; | 230 size_t index = 0; |
| 230 for (const auto& item : obj.headers) { | 231 for (const auto& item : obj.headers) { |
| 231 HttpHeaderPtr header(HttpHeader::New()); | 232 HttpHeaderPtr header(HttpHeader::New()); |
| 232 header->name = item.first; | 233 header->name = item.first; |
| 233 header->value = item.second; | 234 header->value = item.second; |
| 234 request->headers[index++] = header.Pass(); | 235 request->headers[index++] = std::move(header); |
| 235 } | 236 } |
| 236 if (!obj.data.empty()) { | 237 if (!obj.data.empty()) { |
| 237 uint32_t num_bytes = static_cast<uint32_t>(obj.data.size()); | 238 uint32_t num_bytes = static_cast<uint32_t>(obj.data.size()); |
| 238 MojoCreateDataPipeOptions options; | 239 MojoCreateDataPipeOptions options; |
| 239 options.struct_size = sizeof(MojoCreateDataPipeOptions); | 240 options.struct_size = sizeof(MojoCreateDataPipeOptions); |
| 240 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; | 241 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; |
| 241 options.element_num_bytes = 1; | 242 options.element_num_bytes = 1; |
| 242 options.capacity_num_bytes = num_bytes; | 243 options.capacity_num_bytes = num_bytes; |
| 243 DataPipe data_pipe(options); | 244 DataPipe data_pipe(options); |
| 244 request->body = data_pipe.consumer_handle.Pass(); | 245 request->body = std::move(data_pipe.consumer_handle); |
| 245 MojoResult result = | 246 MojoResult result = |
| 246 WriteDataRaw(data_pipe.producer_handle.get(), obj.data.data(), | 247 WriteDataRaw(data_pipe.producer_handle.get(), obj.data.data(), |
| 247 &num_bytes, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE); | 248 &num_bytes, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE); |
| 248 CHECK_EQ(MOJO_RESULT_OK, result); | 249 CHECK_EQ(MOJO_RESULT_OK, result); |
| 249 } | 250 } |
| 250 return request.Pass(); | 251 return request; |
| 251 } | 252 } |
| 252 }; | 253 }; |
| 253 | 254 |
| 254 HttpConnectionImpl::HttpConnectionImpl(int connection_id, | 255 HttpConnectionImpl::HttpConnectionImpl(int connection_id, |
| 255 HttpServerImpl* server, | 256 HttpServerImpl* server, |
| 256 HttpConnectionDelegatePtr delegate, | 257 HttpConnectionDelegatePtr delegate, |
| 257 HttpConnectionPtr* connection) | 258 HttpConnectionPtr* connection) |
| 258 : connection_id_(connection_id), | 259 : connection_id_(connection_id), |
| 259 server_(server), | 260 server_(server), |
| 260 delegate_(delegate.Pass()), | 261 delegate_(std::move(delegate)), |
| 261 binding_(this, connection) { | 262 binding_(this, connection) { |
| 262 DCHECK(delegate_); | 263 DCHECK(delegate_); |
| 263 binding_.set_connection_error_handler([this]() { Close(); }); | 264 binding_.set_connection_error_handler([this]() { Close(); }); |
| 264 delegate_.set_connection_error_handler([this]() { Close(); }); | 265 delegate_.set_connection_error_handler([this]() { Close(); }); |
| 265 } | 266 } |
| 266 | 267 |
| 267 HttpConnectionImpl::~HttpConnectionImpl() { | 268 HttpConnectionImpl::~HttpConnectionImpl() { |
| 268 STLDeleteElements(&response_body_readers_); | 269 STLDeleteElements(&response_body_readers_); |
| 269 } | 270 } |
| 270 | 271 |
| 271 void HttpConnectionImpl::OnReceivedHttpRequest( | 272 void HttpConnectionImpl::OnReceivedHttpRequest( |
| 272 const net::HttpServerRequestInfo& info) { | 273 const net::HttpServerRequestInfo& info) { |
| 273 if (IsClosing()) | 274 if (IsClosing()) |
| 274 return; | 275 return; |
| 275 | 276 |
| 276 delegate_->OnReceivedRequest( | 277 delegate_->OnReceivedRequest( |
| 277 HttpRequest::From(info), [this](HttpResponsePtr response) { | 278 HttpRequest::From(info), [this](HttpResponsePtr response) { |
| 278 if (response->body.is_valid()) { | 279 if (response->body.is_valid()) { |
| 279 SimpleDataPipeReader* reader = new SimpleDataPipeReader; | 280 SimpleDataPipeReader* reader = new SimpleDataPipeReader; |
| 280 response_body_readers_.insert(reader); | 281 response_body_readers_.insert(reader); |
| 281 ScopedDataPipeConsumerHandle body = response->body.Pass(); | 282 ScopedDataPipeConsumerHandle body = std::move(response->body); |
| 282 reader->Start( | 283 reader->Start( |
| 283 body.Pass(), | 284 std::move(body), |
| 284 base::Bind(&HttpConnectionImpl::OnFinishedReadingResponseBody, | 285 base::Bind(&HttpConnectionImpl::OnFinishedReadingResponseBody, |
| 285 base::Unretained(this), base::Passed(&response))); | 286 base::Unretained(this), base::Passed(&response))); |
| 286 } else { | 287 } else { |
| 287 OnFinishedReadingResponseBody(response.Pass(), nullptr, nullptr); | 288 OnFinishedReadingResponseBody(std::move(response), nullptr, nullptr); |
| 288 } | 289 } |
| 289 }); | 290 }); |
| 290 } | 291 } |
| 291 | 292 |
| 292 void HttpConnectionImpl::OnReceivedWebSocketRequest( | 293 void HttpConnectionImpl::OnReceivedWebSocketRequest( |
| 293 const net::HttpServerRequestInfo& info) { | 294 const net::HttpServerRequestInfo& info) { |
| 294 if (IsClosing()) | 295 if (IsClosing()) |
| 295 return; | 296 return; |
| 296 | 297 |
| 297 delegate_->OnReceivedWebSocketRequest( | 298 delegate_->OnReceivedWebSocketRequest( |
| 298 HttpRequest::From(info), | 299 HttpRequest::From(info), |
| 299 [this, info](InterfaceRequest<WebSocket> web_socket, | 300 [this, info](InterfaceRequest<WebSocket> web_socket, |
| 300 ScopedDataPipeConsumerHandle send_stream, | 301 ScopedDataPipeConsumerHandle send_stream, |
| 301 WebSocketClientPtr web_socket_client) { | 302 WebSocketClientPtr web_socket_client) { |
| 302 if (!web_socket.is_pending() || !send_stream.is_valid() || | 303 if (!web_socket.is_pending() || !send_stream.is_valid() || |
| 303 !web_socket_client) { | 304 !web_socket_client) { |
| 304 Close(); | 305 Close(); |
| 305 return; | 306 return; |
| 306 } | 307 } |
| 307 | 308 |
| 308 web_socket_.reset(new WebSocketImpl(this, web_socket.Pass(), | 309 web_socket_.reset(new WebSocketImpl(this, std::move(web_socket), |
| 309 send_stream.Pass(), | 310 std::move(send_stream), |
| 310 web_socket_client.Pass())); | 311 std::move(web_socket_client))); |
| 311 server_->server()->AcceptWebSocket(connection_id_, info); | 312 server_->server()->AcceptWebSocket(connection_id_, info); |
| 312 }); | 313 }); |
| 313 } | 314 } |
| 314 | 315 |
| 315 void HttpConnectionImpl::OnReceivedWebSocketMessage(const std::string& data) { | 316 void HttpConnectionImpl::OnReceivedWebSocketMessage(const std::string& data) { |
| 316 if (IsClosing()) | 317 if (IsClosing()) |
| 317 return; | 318 return; |
| 318 | 319 |
| 319 web_socket_->OnReceivedWebSocketMessage(data); | 320 web_socket_->OnReceivedWebSocketMessage(data); |
| 320 } | 321 } |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 // The close operation is initiated by this object. | 414 // The close operation is initiated by this object. |
| 414 NotifyOwnerCloseIfAllDone(); | 415 NotifyOwnerCloseIfAllDone(); |
| 415 } else { | 416 } else { |
| 416 // The close operation is initiated by |web_socket_|; start closing this | 417 // The close operation is initiated by |web_socket_|; start closing this |
| 417 // object. | 418 // object. |
| 418 Close(); | 419 Close(); |
| 419 } | 420 } |
| 420 } | 421 } |
| 421 | 422 |
| 422 } // namespace mojo | 423 } // namespace mojo |
| OLD | NEW |