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