14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file. 44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "mojo/system/message_pipe.h" 64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/logging.h" 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "mojo/system/channel_endpoint.h" 94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "mojo/system/local_message_pipe_endpoint.h" 104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "mojo/system/message_in_transit.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "mojo/system/message_pipe_dispatcher.h" 124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "mojo/system/message_pipe_endpoint.h" 13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "mojo/system/proxy_message_pipe_endpoint.h" 144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace mojo { 164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace system { 174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciMessagePipe* MessagePipe::CreateLocalLocal() { 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MessagePipe* message_pipe = new MessagePipe(); 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci message_pipe->endpoints_[0].reset(new LocalMessagePipeEndpoint()); 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci message_pipe->endpoints_[1].reset(new LocalMessagePipeEndpoint()); 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return message_pipe; 244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciMessagePipe* MessagePipe::CreateLocalProxy( 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_refptr<ChannelEndpoint>* channel_endpoint) { 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(!channel_endpoint->get()); // Not technically wrong, but unlikely. 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MessagePipe* message_pipe = new MessagePipe(); 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci message_pipe->endpoints_[0].reset(new LocalMessagePipeEndpoint()); 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *channel_endpoint = new ChannelEndpoint(message_pipe, 1); 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci message_pipe->endpoints_[1].reset( 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new ProxyMessagePipeEndpoint(channel_endpoint->get())); 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return message_pipe; 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciMessagePipe* MessagePipe::CreateProxyLocal( 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_refptr<ChannelEndpoint>* channel_endpoint) { 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(!channel_endpoint->get()); // Not technically wrong, but unlikely. 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MessagePipe* message_pipe = new MessagePipe(); 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *channel_endpoint = new ChannelEndpoint(message_pipe, 0); 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci message_pipe->endpoints_[0].reset( 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new ProxyMessagePipeEndpoint(channel_endpoint->get())); 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci message_pipe->endpoints_[1].reset(new LocalMessagePipeEndpoint()); 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return message_pipe; 484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)unsigned MessagePipe::GetPeerPort(unsigned port) { 52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(port == 0 || port == 1); 53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return port ^ 1; 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)MessagePipeEndpoint::Type MessagePipe::GetType(unsigned port) { 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(port == 0 || port == 1); 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::AutoLock locker(lock_); 59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(endpoints_[port]); 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return endpoints_[port]->GetType(); 62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void MessagePipe::CancelAllWaiters(unsigned port) { 654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(port == 0 || port == 1); 664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::AutoLock locker(lock_); 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(endpoints_[port]); 694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) endpoints_[port]->CancelAllWaiters(); 704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void MessagePipe::Close(unsigned port) { 734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(port == 0 || port == 1); 744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) unsigned destination_port = GetPeerPort(port); 764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::AutoLock locker(lock_); 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(endpoints_[port]); 794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) endpoints_[port]->Close(); 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (endpoints_[destination_port]) { 820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!endpoints_[destination_port]->OnPeerClose()) 830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch endpoints_[destination_port].reset(); 840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) endpoints_[port].reset(); 864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// TODO(vtl): Handle flags. 894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)MojoResult MessagePipe::WriteMessage( 904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) unsigned port, 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) UserPointer<const void> bytes, 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint32_t num_bytes, 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<DispatcherTransport>* transports, 944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) MojoWriteMessageFlags flags) { 954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(port == 0 || port == 1); 965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return EnqueueMessageInternal( 97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) GetPeerPort(port), 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) make_scoped_ptr(new MessageInTransit( 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) MessageInTransit::kTypeMessagePipeEndpoint, 100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) MessageInTransit::kSubtypeMessagePipeEndpointData, 101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) num_bytes, 102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bytes)), 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) transports); 1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)MojoResult MessagePipe::ReadMessage(unsigned port, 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) UserPointer<void> bytes, 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) UserPointer<uint32_t> num_bytes, 109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DispatcherVector* dispatchers, 110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) uint32_t* num_dispatchers, 111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) MojoReadMessageFlags flags) { 1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(port == 0 || port == 1); 1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::AutoLock locker(lock_); 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(endpoints_[port]); 1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return endpoints_[port]->ReadMessage( 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bytes, num_bytes, dispatchers, num_dispatchers, flags); 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)HandleSignalsState MessagePipe::GetHandleSignalsState(unsigned port) const { 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(port == 0 || port == 1); 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::AutoLock locker(const_cast<base::Lock&>(lock_)); 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(endpoints_[port]); 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return endpoints_[port]->GetHandleSignalsState(); 1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)MojoResult MessagePipe::AddWaiter(unsigned port, 1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Waiter* waiter, 132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MojoHandleSignals signals, 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint32_t context, 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) HandleSignalsState* signals_state) { 1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(port == 0 || port == 1); 1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::AutoLock locker(lock_); 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(endpoints_[port]); 1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return endpoints_[port]->AddWaiter(waiter, signals, context, signals_state); 1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void MessagePipe::RemoveWaiter(unsigned port, 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Waiter* waiter, 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) HandleSignalsState* signals_state) { 1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(port == 0 || port == 1); 1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::AutoLock locker(lock_); 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(endpoints_[port]); 1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) endpoints_[port]->RemoveWaiter(waiter, signals_state); 1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_refptr<ChannelEndpoint> MessagePipe::ConvertLocalToProxy(unsigned port) { 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(port == 0 || port == 1); 156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::AutoLock locker(lock_); 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(endpoints_[port]); 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(endpoints_[port]->GetType(), MessagePipeEndpoint::kTypeLocal); 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(vtl): Allowing this case is a temporary hack. It'll set up a 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // |MessagePipe| with two proxy endpoints, which will then act as a proxy 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // (rather than trying to connect the two ends directly). 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DLOG_IF(WARNING, 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci !!endpoints_[GetPeerPort(port)] && 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci endpoints_[GetPeerPort(port)]->GetType() != 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MessagePipeEndpoint::kTypeLocal) 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << "Direct message pipe passing across multiple channels not yet " 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "implemented; will proxy"; 170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<MessagePipeEndpoint> old_endpoint(endpoints_[port].Pass()); 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_refptr<ChannelEndpoint> channel_endpoint( 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new ChannelEndpoint(this, port)); 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci endpoints_[port].reset(new ProxyMessagePipeEndpoint(channel_endpoint.get())); 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci channel_endpoint->TakeMessages(static_cast<LocalMessagePipeEndpoint*>( 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci old_endpoint.get())->message_queue()); 1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci old_endpoint->Close(); 178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return channel_endpoint; 180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)MojoResult MessagePipe::EnqueueMessage(unsigned port, 1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<MessageInTransit> message) { 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return EnqueueMessageInternal(port, message.Pass(), nullptr); 1850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid MessagePipe::OnRemove(unsigned port) { 1880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch unsigned destination_port = GetPeerPort(port); 1890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::AutoLock locker(lock_); 1910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // A |OnPeerClose()| can come in first, before |OnRemove()| gets called. 192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!endpoints_[port]) 1930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 1940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (endpoints_[destination_port]) { 1960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!endpoints_[destination_port]->OnPeerClose()) 1970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch endpoints_[destination_port].reset(); 1980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch endpoints_[port].reset(); 200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciMessagePipe::MessagePipe() { 2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)MessagePipe::~MessagePipe() { 2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Owned by the dispatchers. The owning dispatchers should only release us via 2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // their |Close()| method, which should inform us of being closed via our 2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // |Close()|. Thus these should already be null. 209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(!endpoints_[0]); 210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(!endpoints_[1]); 2114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuMojoResult MessagePipe::EnqueueMessageInternal( 2145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu unsigned port, 2155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_ptr<MessageInTransit> message, 2165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::vector<DispatcherTransport>* transports) { 2175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK(port == 0 || port == 1); 218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(message); 2195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (message->type() == MessageInTransit::kTypeMessagePipe) { 2215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK(!transports); 2225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return HandleControlMessage(port, message.Pass()); 2235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK_EQ(message->type(), MessageInTransit::kTypeMessagePipeEndpoint); 2265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::AutoLock locker(lock_); 228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(endpoints_[GetPeerPort(port)]); 2295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // The destination port need not be open, unlike the source port. 231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!endpoints_[port]) 2325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return MOJO_RESULT_FAILED_PRECONDITION; 2335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (transports) { 2355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MojoResult result = AttachTransportsNoLock(port, message.get(), transports); 2365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (result != MOJO_RESULT_OK) 2375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return result; 2385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // The endpoint's |EnqueueMessage()| may not report failure. 2415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu endpoints_[port]->EnqueueMessage(message.Pass()); 2425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return MOJO_RESULT_OK; 2435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 2445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuMojoResult MessagePipe::AttachTransportsNoLock( 2465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu unsigned port, 2475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MessageInTransit* message, 2485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::vector<DispatcherTransport>* transports) { 2495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK(!message->has_dispatchers()); 2505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // You're not allowed to send either handle to a message pipe over the message 2525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // pipe, so check for this. (The case of trying to write a handle to itself is 2535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // taken care of by |Core|. That case kind of makes sense, but leads to 2545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // complications if, e.g., both sides try to do the same thing with their 2555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // respective handles simultaneously. The other case, of trying to write the 2565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // peer handle to a handle, doesn't make sense -- since no handle will be 2575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // available to read the message from.) 2585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (size_t i = 0; i < transports->size(); i++) { 2595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!(*transports)[i].is_valid()) 2605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu continue; 2615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if ((*transports)[i].GetType() == Dispatcher::kTypeMessagePipe) { 2625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MessagePipeDispatcherTransport mp_transport((*transports)[i]); 2635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (mp_transport.GetMessagePipe() == this) { 2645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // The other case should have been disallowed by |Core|. (Note: |port| 2655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // is the peer port of the handle given to |WriteMessage()|.) 2665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK_EQ(mp_transport.GetPort(), port); 2675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return MOJO_RESULT_INVALID_ARGUMENT; 2685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Clone the dispatchers and attach them to the message. (This must be done as 2735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // a separate loop, since we want to leave the dispatchers alone on failure.) 274010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) scoped_ptr<DispatcherVector> dispatchers(new DispatcherVector()); 2755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu dispatchers->reserve(transports->size()); 2765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (size_t i = 0; i < transports->size(); i++) { 2775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if ((*transports)[i].is_valid()) { 2785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu dispatchers->push_back( 2795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu (*transports)[i].CreateEquivalentDispatcherAndClose()); 2805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } else { 2815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu LOG(WARNING) << "Enqueueing null dispatcher"; 2825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu dispatchers->push_back(scoped_refptr<Dispatcher>()); 2835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu message->SetDispatchers(dispatchers.Pass()); 2865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return MOJO_RESULT_OK; 2875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 2885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)MojoResult MessagePipe::HandleControlMessage( 2900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch unsigned /*port*/, 291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<MessageInTransit> message) { 292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG(WARNING) << "Unrecognized MessagePipe control message subtype " 293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << message->subtype(); 294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return MOJO_RESULT_UNKNOWN; 295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 296f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} // namespace system 2984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} // namespace mojo 299