11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved. 21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be 31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file. 41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "mojo/services/public/cpp/network/web_socket_write_queue.h" 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/bind.h" 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace mojo { 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistruct WebSocketWriteQueue::Operation { 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci uint32_t num_bytes_; 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Callback<void(const char*)> callback_; 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const char* data_; 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Only initialized if the initial Write fails. This saves a copy in 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the common case. 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<char> data_copy_; 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciWebSocketWriteQueue::WebSocketWriteQueue(DataPipeProducerHandle handle) 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : handle_(handle), is_waiting_(false) { 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciWebSocketWriteQueue::~WebSocketWriteQueue() { 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid WebSocketWriteQueue::Write(const char* data, 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci uint32_t num_bytes, 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Callback<void(const char*)> callback) { 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Operation* op = new Operation; 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci op->num_bytes_ = num_bytes; 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci op->callback_ = callback; 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci op->data_ = data; 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci queue_.push_back(op); 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MojoResult result = MOJO_RESULT_SHOULD_WAIT; 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!is_waiting_) 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci result = TryToWrite(); 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If we have to wait, make a local copy of the data so we know it will 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // live until we need it. 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (result == MOJO_RESULT_SHOULD_WAIT) { 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci op->data_copy_.resize(num_bytes); 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci memcpy(&op->data_copy_[0], data, num_bytes); 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci op->data_ = &op->data_copy_[0]; 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciMojoResult WebSocketWriteQueue::TryToWrite() { 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Operation* op = queue_[0]; 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci uint32_t bytes_written = op->num_bytes_; 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MojoResult result = WriteDataRaw( 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci handle_, op->data_, &bytes_written, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE); 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (result == MOJO_RESULT_SHOULD_WAIT) { 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Wait(); 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return result; 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Ensure |op| is deleted, whether or not |this| goes away. 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<Operation> op_deleter(op); 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci queue_.weak_erase(queue_.begin()); 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (result != MOJO_RESULT_OK) 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return result; 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci op->callback_.Run(op->data_); // may delete |this| 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return result; 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid WebSocketWriteQueue::Wait() { 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci is_waiting_ = true; 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci handle_watcher_.Start(handle_, 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MOJO_HANDLE_SIGNAL_WRITABLE, 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MOJO_DEADLINE_INDEFINITE, 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&WebSocketWriteQueue::OnHandleReady, 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(this))); 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid WebSocketWriteQueue::OnHandleReady(MojoResult result) { 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci is_waiting_ = false; 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TryToWrite(); 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace mojo 85