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_read_queue.h"
61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/bind.h"
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace mojo {
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistruct WebSocketReadQueue::Operation {
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  uint32_t num_bytes_;
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::Callback<void(const char*)> callback_;
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciWebSocketReadQueue::WebSocketReadQueue(DataPipeConsumerHandle handle)
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : handle_(handle), is_waiting_(false) {
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciWebSocketReadQueue::~WebSocketReadQueue() {
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid WebSocketReadQueue::Read(uint32_t num_bytes,
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              base::Callback<void(const char*)> callback) {
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Operation* op = new Operation;
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  op->num_bytes_ = num_bytes;
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  op->callback_ = callback;
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  queue_.push_back(op);
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!is_waiting_)
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    TryToRead();
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid WebSocketReadQueue::TryToRead() {
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Operation* op = queue_[0];
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const void* buffer = NULL;
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  uint32_t bytes_read = op->num_bytes_;
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MojoResult result = BeginReadDataRaw(
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      handle_, &buffer, &bytes_read, MOJO_READ_DATA_FLAG_ALL_OR_NONE);
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (result == MOJO_RESULT_SHOULD_WAIT) {
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    EndReadDataRaw(handle_, bytes_read);
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Wait();
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Ensure |op| is deleted, whether or not |this| goes away.
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<Operation> op_deleter(op);
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  queue_.weak_erase(queue_.begin());
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (result != MOJO_RESULT_OK)
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DataPipeConsumerHandle handle = handle_;
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  op->callback_.Run(static_cast<const char*>(buffer));  // may delete |this|
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EndReadDataRaw(handle, bytes_read);
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid WebSocketReadQueue::Wait() {
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  is_waiting_ = true;
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  handle_watcher_.Start(
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      handle_,
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MOJO_HANDLE_SIGNAL_READABLE,
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MOJO_DEADLINE_INDEFINITE,
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&WebSocketReadQueue::OnHandleReady, base::Unretained(this)));
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid WebSocketReadQueue::OnHandleReady(MojoResult result) {
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  is_waiting_ = false;
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TryToRead();
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace mojo
71