connector.cc revision 010d83a9304c5a91596085d917d248abff47903a
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/public/cpp/bindings/lib/connector.h"
6
7#include <assert.h>
8#include <stdlib.h>
9
10#include "mojo/public/cpp/bindings/error_handler.h"
11
12namespace mojo {
13namespace internal {
14
15// ----------------------------------------------------------------------------
16
17Connector::Connector(ScopedMessagePipeHandle message_pipe,
18                     MojoAsyncWaiter* waiter)
19    : error_handler_(NULL),
20      waiter_(waiter),
21      message_pipe_(message_pipe.Pass()),
22      incoming_receiver_(NULL),
23      async_wait_id_(0),
24      error_(false),
25      drop_writes_(false),
26      enforce_errors_from_incoming_receiver_(true) {
27  // Even though we don't have an incoming receiver, we still want to monitor
28  // the message pipe to know if is closed or encounters an error.
29  WaitToReadMore();
30}
31
32Connector::~Connector() {
33  if (async_wait_id_)
34    waiter_->CancelWait(waiter_, async_wait_id_);
35}
36
37void Connector::CloseMessagePipe() {
38  Close(message_pipe_.Pass());
39}
40
41bool Connector::Accept(Message* message) {
42  if (error_)
43    return false;
44
45  if (drop_writes_)
46    return true;
47
48  MojoResult rv = WriteMessageRaw(
49      message_pipe_.get(),
50      message->data(),
51      message->data_num_bytes(),
52      message->mutable_handles()->empty() ? NULL :
53          reinterpret_cast<const MojoHandle*>(
54              &message->mutable_handles()->front()),
55      static_cast<uint32_t>(message->mutable_handles()->size()),
56      MOJO_WRITE_MESSAGE_FLAG_NONE);
57
58  switch (rv) {
59    case MOJO_RESULT_OK:
60      // The handles were successfully transferred, so we don't need the message
61      // to track their lifetime any longer.
62      message->mutable_handles()->clear();
63      break;
64    case MOJO_RESULT_FAILED_PRECONDITION:
65      // There's no point in continuing to write to this pipe since the other
66      // end is gone. Avoid writing any future messages. Hide write failures
67      // from the caller since we'd like them to continue consuming any backlog
68      // of incoming messages before regarding the message pipe as closed.
69      drop_writes_ = true;
70      break;
71    default:
72      // This particular write was rejected, presumably because of bad input.
73      // The pipe is not necessarily in a bad state.
74      return false;
75  }
76  return true;
77}
78
79bool Connector::AcceptWithResponder(Message* message,
80                                    MessageReceiver* responder) {
81  // TODO(darin): Implement this!
82  assert(false);
83  return false;
84}
85
86// static
87void Connector::CallOnHandleReady(void* closure, MojoResult result) {
88  Connector* self = static_cast<Connector*>(closure);
89  self->OnHandleReady(result);
90}
91
92void Connector::OnHandleReady(MojoResult result) {
93  async_wait_id_ = 0;
94
95  if (result == MOJO_RESULT_OK) {
96    ReadMore();
97  } else {
98    error_ = true;
99  }
100
101  if (error_ && error_handler_)
102    error_handler_->OnError();
103}
104
105void Connector::WaitToReadMore() {
106  async_wait_id_ = waiter_->AsyncWait(waiter_,
107                                      message_pipe_.get().value(),
108                                      MOJO_WAIT_FLAG_READABLE,
109                                      MOJO_DEADLINE_INDEFINITE,
110                                      &Connector::CallOnHandleReady,
111                                      this);
112}
113
114void Connector::ReadMore() {
115  while (true) {
116    bool receiver_result = false;
117    MojoResult rv =  ReadAndDispatchMessage(
118        message_pipe_.get(), incoming_receiver_, &receiver_result);
119    if (rv == MOJO_RESULT_SHOULD_WAIT) {
120      WaitToReadMore();
121      break;
122    }
123    if (rv != MOJO_RESULT_OK ||
124        (enforce_errors_from_incoming_receiver_ && !receiver_result)) {
125      error_ = true;
126      break;
127    }
128  }
129}
130
131}  // namespace internal
132}  // namespace mojo
133