1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Copyright 2015 The Chromium Authors. All rights reserved. 2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Use of this source code is governed by a BSD-style license that can be 3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// found in the LICENSE file. 4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/cpp/bindings/lib/multiplex_router.h" 6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <stdint.h> 8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <utility> 10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/bind.h" 12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/location.h" 13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/macros.h" 14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/memory/ptr_util.h" 15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/single_thread_task_runner.h" 16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/stl_util.h" 17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/threading/thread_task_runner_handle.h" 18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/cpp/bindings/associated_group.h" 19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/cpp/bindings/interface_endpoint_client.h" 20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/cpp/bindings/interface_endpoint_controller.h" 21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/cpp/bindings/sync_handle_watcher.h" 22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace mojo { 24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace internal { 25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// InterfaceEndpoint stores the information of an interface endpoint registered 27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// with the router. 28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// No one other than the router's |endpoints_| and |tasks_| should hold refs to 29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// this object. 30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass MultiplexRouter::InterfaceEndpoint 31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez : public base::RefCounted<InterfaceEndpoint>, 32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public InterfaceEndpointController { 33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public: 34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceEndpoint(MultiplexRouter* router, InterfaceId id) 35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez : router_(router), 36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez id_(id), 37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez closed_(false), 38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez peer_closed_(false), 39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez client_(nullptr), 40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez event_signalled_(false) {} 41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // --------------------------------------------------------------------------- 43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // The following public methods are safe to call from any threads without 44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // locking. 45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceId id() const { return id_; } 47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // --------------------------------------------------------------------------- 49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // The following public methods are called under the router's lock. 50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool closed() const { return closed_; } 52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez void set_closed() { 53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez router_->lock_.AssertAcquired(); 54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez closed_ = true; 55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool peer_closed() const { return peer_closed_; } 58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez void set_peer_closed() { 59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez router_->lock_.AssertAcquired(); 60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez peer_closed_ = true; 61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::SingleThreadTaskRunner* task_runner() const { 64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return task_runner_.get(); 65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceEndpointClient* client() const { return client_; } 68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez void AttachClient(InterfaceEndpointClient* client, 70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez scoped_refptr<base::SingleThreadTaskRunner> runner) { 71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez router_->lock_.AssertAcquired(); 72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(!client_); 73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(!closed_); 74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(runner->BelongsToCurrentThread()); 75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez task_runner_ = std::move(runner); 77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez client_ = client; 78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // This method must be called on the same thread as the corresponding 81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // AttachClient() call. 82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez void DetachClient() { 83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez router_->lock_.AssertAcquired(); 84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(client_); 85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(task_runner_->BelongsToCurrentThread()); 86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(!closed_); 87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez task_runner_ = nullptr; 89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez client_ = nullptr; 90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sync_watcher_.reset(); 91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez void SignalSyncMessageEvent() { 94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez router_->lock_.AssertAcquired(); 95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (event_signalled_) 96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EnsureEventMessagePipeExists(); 99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez event_signalled_ = true; 100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MojoResult result = 101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez WriteMessageRaw(sync_message_event_sender_.get(), nullptr, 0, nullptr, 102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 0, MOJO_WRITE_MESSAGE_FLAG_NONE); 103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK_EQ(MOJO_RESULT_OK, result); 104645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 105645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 106645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // --------------------------------------------------------------------------- 107645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // The following public methods (i.e., InterfaceEndpointController 108645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // implementation) are called by the client on the same thread as the 109645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // AttachClient() call. They are called outside of the router's lock. 110645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 111645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool SendMessage(Message* message) override { 112645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(task_runner_->BelongsToCurrentThread()); 113645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez message->set_interface_id(id_); 114645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return router_->connector_.Accept(message); 115645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 116645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 117645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez void AllowWokenUpBySyncWatchOnSameThread() override { 118645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(task_runner_->BelongsToCurrentThread()); 119645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 120645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EnsureSyncWatcherExists(); 121645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sync_watcher_->AllowWokenUpBySyncWatchOnSameThread(); 122645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 123645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 124645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool SyncWatch(const bool* should_stop) override { 125645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(task_runner_->BelongsToCurrentThread()); 126645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 127645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EnsureSyncWatcherExists(); 128645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return sync_watcher_->SyncWatch(should_stop); 129645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 130645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 131645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private: 132645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez friend class base::RefCounted<InterfaceEndpoint>; 133645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 134645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ~InterfaceEndpoint() override { 135645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez router_->lock_.AssertAcquired(); 136645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 137645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(!client_); 138645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(closed_); 139645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(peer_closed_); 140645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(!sync_watcher_); 141645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 142645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 143645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez void OnHandleReady(MojoResult result) { 144645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(task_runner_->BelongsToCurrentThread()); 145645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez scoped_refptr<InterfaceEndpoint> self_protector(this); 146645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez scoped_refptr<MultiplexRouter> router_protector(router_); 147645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 148645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Because we never close |sync_message_event_{sender,receiver}_| before 149645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // destruction or set a deadline, |result| should always be MOJO_RESULT_OK. 150645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK_EQ(MOJO_RESULT_OK, result); 151645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool reset_sync_watcher = false; 152645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez { 153645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AutoLock locker(router_->lock_); 154645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 155645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool more_to_process = router_->ProcessFirstSyncMessageForEndpoint(id_); 156645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 157645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!more_to_process) 158645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ResetSyncMessageSignal(); 159645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 160645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Currently there are no queued sync messages and the peer has closed so 161645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // there won't be incoming sync messages in the future. 162645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez reset_sync_watcher = !more_to_process && peer_closed_; 163645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 164645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (reset_sync_watcher) { 165645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // If a SyncWatch() call (or multiple ones) of this interface endpoint is 166645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // on the call stack, resetting the sync watcher will allow it to exit 167645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // when the call stack unwinds to that frame. 168645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sync_watcher_.reset(); 169645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 170645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 171645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 172645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez void EnsureSyncWatcherExists() { 173645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(task_runner_->BelongsToCurrentThread()); 174645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (sync_watcher_) 175645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 176645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 177645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez { 178645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AutoLock locker(router_->lock_); 179645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EnsureEventMessagePipeExists(); 180645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 181645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez auto iter = router_->sync_message_tasks_.find(id_); 182645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (iter != router_->sync_message_tasks_.end() && !iter->second.empty()) 183645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez SignalSyncMessageEvent(); 184645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 185645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 186645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sync_watcher_.reset(new SyncHandleWatcher( 187645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sync_message_event_receiver_.get(), MOJO_HANDLE_SIGNAL_READABLE, 188645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::Bind(&InterfaceEndpoint::OnHandleReady, base::Unretained(this)))); 189645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 190645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 191645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez void EnsureEventMessagePipeExists() { 192645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez router_->lock_.AssertAcquired(); 193645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 194645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (sync_message_event_receiver_.is_valid()) 195645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 196645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 197645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MojoResult result = CreateMessagePipe(nullptr, &sync_message_event_sender_, 198645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez &sync_message_event_receiver_); 199645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK_EQ(MOJO_RESULT_OK, result); 200645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 201645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 202645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez void ResetSyncMessageSignal() { 203645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez router_->lock_.AssertAcquired(); 204645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 205645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!event_signalled_) 206645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 207645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 208645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(sync_message_event_receiver_.is_valid()); 209645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MojoResult result = ReadMessageRaw(sync_message_event_receiver_.get(), 210645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez nullptr, nullptr, nullptr, nullptr, 211645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MOJO_READ_MESSAGE_FLAG_MAY_DISCARD); 212645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK_EQ(MOJO_RESULT_OK, result); 213645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez event_signalled_ = false; 214645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 215645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 216645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // --------------------------------------------------------------------------- 217645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // The following members are safe to access from any threads. 218645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 219645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MultiplexRouter* const router_; 220645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const InterfaceId id_; 221645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 222645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // --------------------------------------------------------------------------- 223645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // The following members are accessed under the router's lock. 224645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 225645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Whether the endpoint has been closed. 226645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool closed_; 227645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Whether the peer endpoint has been closed. 228645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool peer_closed_; 229645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 230645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // The task runner on which |client_|'s methods can be called. 231645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 232645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Not owned. It is null if no client is attached to this endpoint. 233645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceEndpointClient* client_; 234645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 235645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // A message pipe used as an event to signal that sync messages are available. 236645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // The message pipe handles are initialized under the router's lock and remain 237645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // unchanged afterwards. They may be accessed outside of the router's lock 238645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // later. 239645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ScopedMessagePipeHandle sync_message_event_sender_; 240645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ScopedMessagePipeHandle sync_message_event_receiver_; 241645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool event_signalled_; 242645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 243645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // --------------------------------------------------------------------------- 244645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // The following members are only valid while a client is attached. They are 245645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // used exclusively on the client's thread. They may be accessed outside of 246645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // the router's lock. 247645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 248645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez std::unique_ptr<SyncHandleWatcher> sync_watcher_; 249645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 250645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DISALLOW_COPY_AND_ASSIGN(InterfaceEndpoint); 251645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}; 252645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 253645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezstruct MultiplexRouter::Task { 254645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public: 255645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Doesn't take ownership of |message| but takes its contents. 256645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez static std::unique_ptr<Task> CreateMessageTask(Message* message) { 257645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Task* task = new Task(MESSAGE); 258645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez task->message.reset(new Message); 259645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez message->MoveTo(task->message.get()); 260645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return base::WrapUnique(task); 261645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 262645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez static std::unique_ptr<Task> CreateNotifyErrorTask( 263645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceEndpoint* endpoint) { 264645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Task* task = new Task(NOTIFY_ERROR); 265645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez task->endpoint_to_notify = endpoint; 266645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return base::WrapUnique(task); 267645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 268645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 269645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ~Task() {} 270645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 271645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool IsMessageTask() const { return type == MESSAGE; } 272645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool IsNotifyErrorTask() const { return type == NOTIFY_ERROR; } 273645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 274645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez std::unique_ptr<Message> message; 275645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez scoped_refptr<InterfaceEndpoint> endpoint_to_notify; 276645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 277645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez enum Type { MESSAGE, NOTIFY_ERROR }; 278645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Type type; 279645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 280645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private: 281645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez explicit Task(Type in_type) : type(in_type) {} 282645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}; 283645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 284645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezMultiplexRouter::MultiplexRouter( 285645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool set_interface_id_namesapce_bit, 286645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ScopedMessagePipeHandle message_pipe, 287645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez scoped_refptr<base::SingleThreadTaskRunner> runner) 288645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez : AssociatedGroupController(base::ThreadTaskRunnerHandle::Get()), 289645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez set_interface_id_namespace_bit_(set_interface_id_namesapce_bit), 290645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez header_validator_(this), 291645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez connector_(std::move(message_pipe), 292645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Connector::MULTI_THREADED_SEND, 293645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez std::move(runner)), 294645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez control_message_handler_(this), 295645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez control_message_proxy_(&connector_), 296645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez next_interface_id_value_(1), 297645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez posted_to_process_tasks_(false), 298645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encountered_error_(false), 299645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez testing_mode_(false) { 300645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Always participate in sync handle watching, because even if it doesn't 301645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // expect sync requests during sync handle watching, it may still need to 302645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // dispatch messages to associated endpoints on a different thread. 303645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez connector_.AllowWokenUpBySyncWatchOnSameThread(); 304645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez connector_.set_incoming_receiver(&header_validator_); 305645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez connector_.set_connection_error_handler( 306645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::Bind(&MultiplexRouter::OnPipeConnectionError, 307645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::Unretained(this))); 308645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 309645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 310645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezMultiplexRouter::~MultiplexRouter() { 311645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AutoLock locker(lock_); 312645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 313645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sync_message_tasks_.clear(); 314645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez tasks_.clear(); 315645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 316645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (auto iter = endpoints_.begin(); iter != endpoints_.end();) { 317645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceEndpoint* endpoint = iter->second.get(); 318645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Increment the iterator before calling UpdateEndpointStateMayRemove() 319645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // because it may remove the corresponding value from the map. 320645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ++iter; 321645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 322645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(endpoint->closed()); 323645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); 324645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 325645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 326645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(endpoints_.empty()); 327645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 328645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 329645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MultiplexRouter::SetMasterInterfaceName(const std::string& name) { 330645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(thread_checker_.CalledOnValidThread()); 331645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez header_validator_.SetDescription(name + " [master] MessageHeaderValidator"); 332645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez control_message_handler_.SetDescription( 333645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez name + " [master] PipeControlMessageHandler"); 334645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 335645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 336645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MultiplexRouter::CreateEndpointHandlePair( 337645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ScopedInterfaceEndpointHandle* local_endpoint, 338645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ScopedInterfaceEndpointHandle* remote_endpoint) { 339645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AutoLock locker(lock_); 340645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez uint32_t id = 0; 341645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez do { 342645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (next_interface_id_value_ >= kInterfaceIdNamespaceMask) 343645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez next_interface_id_value_ = 1; 344645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez id = next_interface_id_value_++; 345645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (set_interface_id_namespace_bit_) 346645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez id |= kInterfaceIdNamespaceMask; 347645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } while (ContainsKey(endpoints_, id)); 348645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 349645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceEndpoint* endpoint = new InterfaceEndpoint(this, id); 350645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez endpoints_[id] = endpoint; 351645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (encountered_error_) 352645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); 353645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 354645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez *local_endpoint = CreateScopedInterfaceEndpointHandle(id, true); 355645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez *remote_endpoint = CreateScopedInterfaceEndpointHandle(id, false); 356645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 357645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 358645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezScopedInterfaceEndpointHandle MultiplexRouter::CreateLocalEndpointHandle( 359645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceId id) { 360645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!IsValidInterfaceId(id)) 361645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return ScopedInterfaceEndpointHandle(); 362645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 363645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AutoLock locker(lock_); 364645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool inserted = false; 365645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceEndpoint* endpoint = FindOrInsertEndpoint(id, &inserted); 366645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (inserted) { 367645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (encountered_error_) 368645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); 369645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 370645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // If the endpoint already exist, it is because we have received a 371645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // notification that the peer endpoint has closed. 372645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CHECK(!endpoint->closed()); 373645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CHECK(endpoint->peer_closed()); 374645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 375645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return CreateScopedInterfaceEndpointHandle(id, true); 376645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 377645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 378645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MultiplexRouter::CloseEndpointHandle(InterfaceId id, bool is_local) { 379645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!IsValidInterfaceId(id)) 380645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 381645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 382645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AutoLock locker(lock_); 383645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 384645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!is_local) { 385645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(ContainsKey(endpoints_, id)); 386645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(!IsMasterInterfaceId(id)); 387645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 388645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // We will receive a NotifyPeerEndpointClosed message from the other side. 389645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez control_message_proxy_.NotifyEndpointClosedBeforeSent(id); 390645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 391645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 392645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 393645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 394645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(ContainsKey(endpoints_, id)); 395645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceEndpoint* endpoint = endpoints_[id].get(); 396645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(!endpoint->client()); 397645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(!endpoint->closed()); 398645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UpdateEndpointStateMayRemove(endpoint, ENDPOINT_CLOSED); 399645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 400645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!IsMasterInterfaceId(id)) 401645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez control_message_proxy_.NotifyPeerEndpointClosed(id); 402645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 403645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr); 404645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 405645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 406645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezInterfaceEndpointController* MultiplexRouter::AttachEndpointClient( 407645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const ScopedInterfaceEndpointHandle& handle, 408645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceEndpointClient* client, 409645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez scoped_refptr<base::SingleThreadTaskRunner> runner) { 410645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const InterfaceId id = handle.id(); 411645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 412645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(IsValidInterfaceId(id)); 413645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(client); 414645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 415645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AutoLock locker(lock_); 416645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(ContainsKey(endpoints_, id)); 417645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 418645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceEndpoint* endpoint = endpoints_[id].get(); 419645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez endpoint->AttachClient(client, std::move(runner)); 420645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 421645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (endpoint->peer_closed()) 422645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); 423645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr); 424645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 425645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return endpoint; 426645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 427645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 428645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MultiplexRouter::DetachEndpointClient( 429645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const ScopedInterfaceEndpointHandle& handle) { 430645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const InterfaceId id = handle.id(); 431645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 432645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(IsValidInterfaceId(id)); 433645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 434645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AutoLock locker(lock_); 435645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(ContainsKey(endpoints_, id)); 436645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 437645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceEndpoint* endpoint = endpoints_[id].get(); 438645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez endpoint->DetachClient(); 439645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 440645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 441645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MultiplexRouter::RaiseError() { 442645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (task_runner_->BelongsToCurrentThread()) { 443645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez connector_.RaiseError(); 444645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 445645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez task_runner_->PostTask(FROM_HERE, 446645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::Bind(&MultiplexRouter::RaiseError, this)); 447645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 448645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 449645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 450645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MultiplexRouter::CloseMessagePipe() { 451645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(thread_checker_.CalledOnValidThread()); 452645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez connector_.CloseMessagePipe(); 453645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // CloseMessagePipe() above won't trigger connection error handler. 454645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Explicitly call OnPipeConnectionError() so that associated endpoints will 455645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // get notified. 456645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez OnPipeConnectionError(); 457645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 458645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 459645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool MultiplexRouter::HasAssociatedEndpoints() const { 460645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(thread_checker_.CalledOnValidThread()); 461645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AutoLock locker(lock_); 462645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 463645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (endpoints_.size() > 1) 464645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 465645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (endpoints_.size() == 0) 466645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 467645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 468645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return !ContainsKey(endpoints_, kMasterInterfaceId); 469645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 470645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 471645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MultiplexRouter::EnableTestingMode() { 472645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(thread_checker_.CalledOnValidThread()); 473645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AutoLock locker(lock_); 474645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 475645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez testing_mode_ = true; 476645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez connector_.set_enforce_errors_from_incoming_receiver(false); 477645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 478645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 479645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool MultiplexRouter::Accept(Message* message) { 480645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(thread_checker_.CalledOnValidThread()); 481645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 482645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez scoped_refptr<MultiplexRouter> protector(this); 483645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AutoLock locker(lock_); 484645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 485645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ClientCallBehavior client_call_behavior = 486645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez connector_.during_sync_handle_watcher_callback() 487645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ? ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES 488645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez : ALLOW_DIRECT_CLIENT_CALLS; 489645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 490645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool processed = 491645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez tasks_.empty() && ProcessIncomingMessage(message, client_call_behavior, 492645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez connector_.task_runner()); 493645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 494645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!processed) { 495645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Either the task queue is not empty or we cannot process the message 496645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // directly. In both cases, there is no need to call ProcessTasks(). 497645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez tasks_.push_back(Task::CreateMessageTask(message)); 498645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Task* task = tasks_.back().get(); 499645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 500645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (task->message->has_flag(Message::kFlagIsSync)) { 501645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceId id = task->message->interface_id(); 502645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sync_message_tasks_[id].push_back(task); 503645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez auto iter = endpoints_.find(id); 504645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (iter != endpoints_.end()) 505645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez iter->second->SignalSyncMessageEvent(); 506645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 507645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else if (!tasks_.empty()) { 508645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Processing the message may result in new tasks (for error notification) 509645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // being added to the queue. In this case, we have to attempt to process the 510645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // tasks. 511645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ProcessTasks(client_call_behavior, connector_.task_runner()); 512645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 513645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 514645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Always return true. If we see errors during message processing, we will 515645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // explicitly call Connector::RaiseError() to disconnect the message pipe. 516645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 517645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 518645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 519645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool MultiplexRouter::OnPeerAssociatedEndpointClosed(InterfaceId id) { 520645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez lock_.AssertAcquired(); 521645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 522645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (IsMasterInterfaceId(id)) 523645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 524645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 525645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceEndpoint* endpoint = FindOrInsertEndpoint(id, nullptr); 526645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 527645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // It is possible that this endpoint has been set as peer closed. That is 528645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // because when the message pipe is closed, all the endpoints are updated with 529645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // PEER_ENDPOINT_CLOSED. We continue to process remaining tasks in the queue, 530645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // as long as there are refs keeping the router alive. If there is a 531645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // PeerAssociatedEndpointClosedEvent control message in the queue, we will get 532645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // here and see that the endpoint has been marked as peer closed. 533645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!endpoint->peer_closed()) { 534645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (endpoint->client()) 535645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); 536645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); 537645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 538645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 539645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // No need to trigger a ProcessTasks() because it is already on the stack. 540645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 541645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 542645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 543645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 544645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool MultiplexRouter::OnAssociatedEndpointClosedBeforeSent(InterfaceId id) { 545645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez lock_.AssertAcquired(); 546645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 547645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (IsMasterInterfaceId(id)) 548645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 549645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 550645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceEndpoint* endpoint = FindOrInsertEndpoint(id, nullptr); 551645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(!endpoint->closed()); 552645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UpdateEndpointStateMayRemove(endpoint, ENDPOINT_CLOSED); 553645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 554645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez control_message_proxy_.NotifyPeerEndpointClosed(id); 555645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 556645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 557645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 558645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 559645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MultiplexRouter::OnPipeConnectionError() { 560645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(thread_checker_.CalledOnValidThread()); 561645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 562645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez scoped_refptr<MultiplexRouter> protector(this); 563645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AutoLock locker(lock_); 564645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 565645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encountered_error_ = true; 566645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 567645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (auto iter = endpoints_.begin(); iter != endpoints_.end();) { 568645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceEndpoint* endpoint = iter->second.get(); 569645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Increment the iterator before calling UpdateEndpointStateMayRemove() 570645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // because it may remove the corresponding value from the map. 571645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ++iter; 572645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 573645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (endpoint->client()) 574645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); 575645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 576645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); 577645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 578645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 579645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ProcessTasks(connector_.during_sync_handle_watcher_callback() 580645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ? ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES 581645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez : ALLOW_DIRECT_CLIENT_CALLS, 582645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez connector_.task_runner()); 583645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 584645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 585645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MultiplexRouter::ProcessTasks( 586645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ClientCallBehavior client_call_behavior, 587645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::SingleThreadTaskRunner* current_task_runner) { 588645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez lock_.AssertAcquired(); 589645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 590645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (posted_to_process_tasks_) 591645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 592645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 593645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez while (!tasks_.empty()) { 594645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez std::unique_ptr<Task> task(std::move(tasks_.front())); 595645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez tasks_.pop_front(); 596645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 597645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceId id = kInvalidInterfaceId; 598645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool sync_message = task->IsMessageTask() && task->message && 599645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez task->message->has_flag(Message::kFlagIsSync); 600645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (sync_message) { 601645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez id = task->message->interface_id(); 602645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez auto& sync_message_queue = sync_message_tasks_[id]; 603645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK_EQ(task.get(), sync_message_queue.front()); 604645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sync_message_queue.pop_front(); 605645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 606645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 607645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool processed = 608645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez task->IsNotifyErrorTask() 609645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ? ProcessNotifyErrorTask(task.get(), client_call_behavior, 610645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez current_task_runner) 611645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez : ProcessIncomingMessage(task->message.get(), client_call_behavior, 612645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez current_task_runner); 613645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 614645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!processed) { 615645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (sync_message) { 616645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez auto& sync_message_queue = sync_message_tasks_[id]; 617645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sync_message_queue.push_front(task.get()); 618645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 619645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez tasks_.push_front(std::move(task)); 620645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez break; 621645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 622645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (sync_message) { 623645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez auto iter = sync_message_tasks_.find(id); 624645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (iter != sync_message_tasks_.end() && iter->second.empty()) 625645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sync_message_tasks_.erase(iter); 626645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 627645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 628645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 629645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 630645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 631645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool MultiplexRouter::ProcessFirstSyncMessageForEndpoint(InterfaceId id) { 632645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez lock_.AssertAcquired(); 633645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 634645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez auto iter = sync_message_tasks_.find(id); 635645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (iter == sync_message_tasks_.end()) 636645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 637645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 638645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MultiplexRouter::Task* task = iter->second.front(); 639645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez iter->second.pop_front(); 640645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 641645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(task->IsMessageTask()); 642645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez std::unique_ptr<Message> message(std::move(task->message)); 643645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 644645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Note: after this call, |task| and |iter| may be invalidated. 645645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool processed = ProcessIncomingMessage( 646645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez message.get(), ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES, nullptr); 647645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(processed); 648645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 649645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez iter = sync_message_tasks_.find(id); 650645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (iter == sync_message_tasks_.end()) 651645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 652645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 653645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (iter->second.empty()) { 654645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sync_message_tasks_.erase(iter); 655645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 656645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 657645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 658645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 659645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 660645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 661645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool MultiplexRouter::ProcessNotifyErrorTask( 662645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Task* task, 663645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ClientCallBehavior client_call_behavior, 664645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::SingleThreadTaskRunner* current_task_runner) { 665645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(!current_task_runner || current_task_runner->BelongsToCurrentThread()); 666645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez lock_.AssertAcquired(); 667645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceEndpoint* endpoint = task->endpoint_to_notify.get(); 668645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!endpoint->client()) 669645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 670645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 671645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (client_call_behavior != ALLOW_DIRECT_CLIENT_CALLS || 672645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez endpoint->task_runner() != current_task_runner) { 673645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MaybePostToProcessTasks(endpoint->task_runner()); 674645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 675645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 676645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 677645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(endpoint->task_runner()->BelongsToCurrentThread()); 678645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 679645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceEndpointClient* client = endpoint->client(); 680645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez { 681645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // We must unlock before calling into |client| because it may call this 682645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // object within NotifyError(). Holding the lock will lead to deadlock. 683645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // 684645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // It is safe to call into |client| without the lock. Because |client| is 685645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // always accessed on the same thread, including DetachEndpointClient(). 686645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AutoUnlock unlocker(lock_); 687645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez client->NotifyError(); 688645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 689645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 690645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 691645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 692645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool MultiplexRouter::ProcessIncomingMessage( 693645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Message* message, 694645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ClientCallBehavior client_call_behavior, 695645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::SingleThreadTaskRunner* current_task_runner) { 696645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(!current_task_runner || current_task_runner->BelongsToCurrentThread()); 697645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez lock_.AssertAcquired(); 698645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 699645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!message) { 700645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // This is a sync message and has been processed during sync handle 701645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // watching. 702645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 703645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 704645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 705645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (PipeControlMessageHandler::IsPipeControlMessage(message)) { 706645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!control_message_handler_.Accept(message)) 707645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez RaiseErrorInNonTestingMode(); 708645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 709645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 710645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 711645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceId id = message->interface_id(); 712645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(IsValidInterfaceId(id)); 713645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 714645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool inserted = false; 715645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceEndpoint* endpoint = FindOrInsertEndpoint(id, &inserted); 716645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (inserted) { 717645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Currently, it is legitimate to receive messages for an endpoint 718645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // that is not registered. For example, the endpoint is transferred in 719645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // a message that is discarded. Once we add support to specify all 720645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // enclosing endpoints in message header, we should be able to remove 721645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // this. 722645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UpdateEndpointStateMayRemove(endpoint, ENDPOINT_CLOSED); 723645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 724645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // It is also possible that this newly-inserted endpoint is the master 725645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // endpoint. When the master InterfacePtr/Binding goes away, the message 726645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // pipe is closed and we explicitly trigger a pipe connection error. The 727645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // error updates all the endpoints, including the master endpoint, with 728645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // PEER_ENDPOINT_CLOSED and removes the master endpoint from the 729645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // registration. We continue to process remaining tasks in the queue, as 730645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // long as there are refs keeping the router alive. If there are remaining 731645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // messages for the master endpoint, we will get here. 732645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!IsMasterInterfaceId(id)) 733645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez control_message_proxy_.NotifyPeerEndpointClosed(id); 734645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 735645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 736645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 737645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (endpoint->closed()) 738645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 739645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 740645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!endpoint->client()) { 741645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // We need to wait until a client is attached in order to dispatch further 742645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // messages. 743645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 744645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 745645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 746645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool can_direct_call; 747645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (message->has_flag(Message::kFlagIsSync)) { 748645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez can_direct_call = client_call_behavior != NO_DIRECT_CLIENT_CALLS && 749645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez endpoint->task_runner()->BelongsToCurrentThread(); 750645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 751645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez can_direct_call = client_call_behavior == ALLOW_DIRECT_CLIENT_CALLS && 752645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez endpoint->task_runner() == current_task_runner; 753645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 754645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 755645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!can_direct_call) { 756645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MaybePostToProcessTasks(endpoint->task_runner()); 757645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 758645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 759645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 760645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(endpoint->task_runner()->BelongsToCurrentThread()); 761645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 762645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceEndpointClient* client = endpoint->client(); 763645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool result = false; 764645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez { 765645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // We must unlock before calling into |client| because it may call this 766645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // object within HandleIncomingMessage(). Holding the lock will lead to 767645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // deadlock. 768645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // 769645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // It is safe to call into |client| without the lock. Because |client| is 770645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // always accessed on the same thread, including DetachEndpointClient(). 771645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AutoUnlock unlocker(lock_); 772645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez result = client->HandleIncomingMessage(message); 773645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 774645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!result) 775645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez RaiseErrorInNonTestingMode(); 776645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 777645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 778645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 779645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 780645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MultiplexRouter::MaybePostToProcessTasks( 781645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::SingleThreadTaskRunner* task_runner) { 782645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez lock_.AssertAcquired(); 783645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (posted_to_process_tasks_) 784645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 785645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 786645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez posted_to_process_tasks_ = true; 787645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez posted_to_task_runner_ = task_runner; 788645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez task_runner->PostTask( 789645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez FROM_HERE, base::Bind(&MultiplexRouter::LockAndCallProcessTasks, this)); 790645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 791645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 792645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MultiplexRouter::LockAndCallProcessTasks() { 793645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // There is no need to hold a ref to this class in this case because this is 794645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // always called using base::Bind(), which holds a ref. 795645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AutoLock locker(lock_); 796645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez posted_to_process_tasks_ = false; 797645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez scoped_refptr<base::SingleThreadTaskRunner> runner( 798645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez std::move(posted_to_task_runner_)); 799645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ProcessTasks(ALLOW_DIRECT_CLIENT_CALLS, runner.get()); 800645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 801645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 802645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MultiplexRouter::UpdateEndpointStateMayRemove( 803645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceEndpoint* endpoint, 804645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EndpointStateUpdateType type) { 805645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez switch (type) { 806645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez case ENDPOINT_CLOSED: 807645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez endpoint->set_closed(); 808645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez break; 809645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez case PEER_ENDPOINT_CLOSED: 810645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez endpoint->set_peer_closed(); 811645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // If the interface endpoint is performing a sync watch, this makes sure 812645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // it is notified and eventually exits the sync watch. 813645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez endpoint->SignalSyncMessageEvent(); 814645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez break; 815645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 816645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (endpoint->closed() && endpoint->peer_closed()) 817645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez endpoints_.erase(endpoint->id()); 818645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 819645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 820645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MultiplexRouter::RaiseErrorInNonTestingMode() { 821645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez lock_.AssertAcquired(); 822645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!testing_mode_) 823645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez RaiseError(); 824645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 825645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 826645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezMultiplexRouter::InterfaceEndpoint* MultiplexRouter::FindOrInsertEndpoint( 827645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceId id, 828645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool* inserted) { 829645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez lock_.AssertAcquired(); 830645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Either |inserted| is nullptr or it points to a boolean initialized as 831645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // false. 832645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(!inserted || !*inserted); 833645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 834645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez auto iter = endpoints_.find(id); 835645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez InterfaceEndpoint* endpoint; 836645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (iter == endpoints_.end()) { 837645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez endpoint = new InterfaceEndpoint(this, id); 838645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez endpoints_[id] = endpoint; 839645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (inserted) 840645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez *inserted = true; 841645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 842645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez endpoint = iter->second.get(); 843645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 844645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 845645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return endpoint; 846645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 847645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 848645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace internal 849645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace mojo 850