1// Copyright 2013 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.
4
5#include "mojo/system/data_pipe_consumer_dispatcher.h"
6
7#include "base/logging.h"
8#include "mojo/system/data_pipe.h"
9#include "mojo/system/memory.h"
10
11namespace mojo {
12namespace system {
13
14DataPipeConsumerDispatcher::DataPipeConsumerDispatcher() {
15}
16
17void DataPipeConsumerDispatcher::Init(scoped_refptr<DataPipe> data_pipe) {
18  DCHECK(data_pipe.get());
19  data_pipe_ = data_pipe;
20}
21
22DataPipeConsumerDispatcher::~DataPipeConsumerDispatcher() {
23  // |Close()|/|CloseImplNoLock()| should have taken care of the pipe.
24  DCHECK(!data_pipe_.get());
25}
26
27void DataPipeConsumerDispatcher::CancelAllWaitersNoLock() {
28  lock().AssertAcquired();
29  data_pipe_->ConsumerCancelAllWaiters();
30}
31
32MojoResult DataPipeConsumerDispatcher::CloseImplNoLock() {
33  lock().AssertAcquired();
34  data_pipe_->ConsumerClose();
35  data_pipe_ = NULL;
36  return MOJO_RESULT_OK;
37}
38
39MojoResult DataPipeConsumerDispatcher::ReadDataImplNoLock(
40    void* elements,
41    uint32_t* num_elements,
42    MojoReadDataFlags flags) {
43  lock().AssertAcquired();
44
45  if (!VerifyUserPointer<uint32_t>(num_elements, 1))
46    return MOJO_RESULT_INVALID_ARGUMENT;
47  // These flags are mutally exclusive.
48  if ((flags & MOJO_READ_DATA_FLAG_DISCARD) &&
49      (flags & MOJO_READ_DATA_FLAG_QUERY))
50    return MOJO_RESULT_INVALID_ARGUMENT;
51  if ((flags & MOJO_READ_DATA_FLAG_DISCARD) ||
52      (flags & MOJO_READ_DATA_FLAG_QUERY)) {
53    DVLOG_IF(2, elements) << "Discard/query mode: ignoring non-null |elements|";
54    elements = NULL;  // Null it out for safety.
55  } else {
56    // Only verify |elements| if we're neither discarding nor querying.
57    if (!VerifyUserPointerForSize(elements, data_pipe_->element_size(),
58                                  *num_elements))
59      return MOJO_RESULT_INVALID_ARGUMENT;
60  }
61
62  return data_pipe_->ConsumerReadData(elements, num_elements, flags);
63}
64
65MojoResult DataPipeConsumerDispatcher::BeginReadDataImplNoLock(
66    const void** buffer,
67    uint32_t* buffer_num_elements,
68    MojoReadDataFlags flags) {
69  lock().AssertAcquired();
70
71  if (!VerifyUserPointer<const void*>(buffer, 1))
72    return MOJO_RESULT_INVALID_ARGUMENT;
73  if (!VerifyUserPointer<uint32_t>(buffer_num_elements, 1))
74    return MOJO_RESULT_INVALID_ARGUMENT;
75  // These flags may not be used in two-phase mode.
76  if ((flags & MOJO_READ_DATA_FLAG_DISCARD) ||
77      (flags & MOJO_READ_DATA_FLAG_QUERY))
78    return MOJO_RESULT_INVALID_ARGUMENT;
79
80  return data_pipe_->ConsumerBeginReadData(buffer, buffer_num_elements, flags);
81}
82
83MojoResult DataPipeConsumerDispatcher::EndReadDataImplNoLock(
84    uint32_t num_elements_read) {
85  lock().AssertAcquired();
86
87  return data_pipe_->ConsumerEndReadData(num_elements_read);
88}
89
90MojoResult DataPipeConsumerDispatcher::AddWaiterImplNoLock(
91    Waiter* waiter,
92    MojoWaitFlags flags,
93    MojoResult wake_result) {
94  lock().AssertAcquired();
95  return data_pipe_->ConsumerAddWaiter(waiter, flags, wake_result);
96}
97
98void DataPipeConsumerDispatcher::RemoveWaiterImplNoLock(Waiter* waiter) {
99  lock().AssertAcquired();
100  data_pipe_->ConsumerRemoveWaiter(waiter);
101}
102
103scoped_refptr<Dispatcher>
104DataPipeConsumerDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() {
105  lock().AssertAcquired();
106
107  scoped_refptr<DataPipeConsumerDispatcher> rv =
108      new DataPipeConsumerDispatcher();
109  rv->Init(data_pipe_);
110  data_pipe_ = NULL;
111  return scoped_refptr<Dispatcher>(rv.get());
112}
113
114}  // namespace system
115}  // namespace mojo
116