#include "base/logging.h"
#include "mojo/system/channel.h"
-#include "mojo/system/dispatcher.h"
#include "mojo/system/local_message_pipe_endpoint.h"
#include "mojo/system/message_in_transit.h"
+#include "mojo/system/message_pipe_dispatcher.h"
#include "mojo/system/message_pipe_endpoint.h"
#include "mojo/system/proxy_message_pipe_endpoint.h"
// TODO(vtl): Handle flags.
MojoResult MessagePipe::WriteMessage(
unsigned port,
- const void* bytes, uint32_t num_bytes,
- const std::vector<Dispatcher*>* dispatchers,
+ const void* bytes,
+ uint32_t num_bytes,
+ std::vector<DispatcherTransport>* transports,
MojoWriteMessageFlags flags) {
DCHECK(port == 0 || port == 1);
+ uint32_t num_handles =
+ transports ? static_cast<uint32_t>(transports->size()) : 0;
return EnqueueMessage(
GetPeerPort(port),
MessageInTransit::Create(
MessageInTransit::kTypeMessagePipeEndpoint,
MessageInTransit::kSubtypeMessagePipeEndpointData,
- bytes, num_bytes),
- dispatchers);
+ bytes, num_bytes, num_handles),
+ transports);
}
MojoResult MessagePipe::ReadMessage(
unsigned port,
- void* bytes, uint32_t* num_bytes,
+ void* bytes,
+ uint32_t* num_bytes,
std::vector<scoped_refptr<Dispatcher> >* dispatchers,
uint32_t* num_dispatchers,
MojoReadMessageFlags flags) {
base::AutoLock locker(lock_);
DCHECK(endpoints_[port].get());
- return endpoints_[port]->ReadMessage(bytes, num_bytes,
- dispatchers, num_dispatchers,
- flags);
+ return endpoints_[port]->ReadMessage(bytes, num_bytes, dispatchers,
+ num_dispatchers, flags);
}
MojoResult MessagePipe::AddWaiter(unsigned port,
MojoResult MessagePipe::EnqueueMessage(
unsigned port,
MessageInTransit* message,
- const std::vector<Dispatcher*>* dispatchers) {
+ std::vector<DispatcherTransport>* transports) {
DCHECK(port == 0 || port == 1);
DCHECK(message);
+ DCHECK((!transports && message->num_handles() == 0) ||
+ (transports && transports->size() > 0 &&
+ message->num_handles() == transports->size()));
if (message->type() == MessageInTransit::kTypeMessagePipe) {
- DCHECK(!dispatchers);
+ DCHECK(!transports);
return HandleControlMessage(port, message);
}
return MOJO_RESULT_FAILED_PRECONDITION;
}
- MojoResult result = endpoints_[port]->CanEnqueueMessage(message, dispatchers);
- if (result != MOJO_RESULT_OK) {
- message->Destroy();
- return result;
- }
-
- if (dispatchers) {
- DCHECK(!dispatchers->empty());
-
- std::vector<scoped_refptr<Dispatcher> > replacement_dispatchers;
- for (size_t i = 0; i < dispatchers->size(); i++) {
- replacement_dispatchers.push_back(
- (*dispatchers)[i]->CreateEquivalentDispatcherAndCloseNoLock());
+ if (transports) {
+ // You're not allowed to send either handle to a message pipe over the
+ // message pipe, so check for this. (The case of trying to write a handle to
+ // itself is taken care of by |CoreImpl|. That case kind of makes sense, but
+ // leads to complications if, e.g., both sides try to do the same thing with
+ // their respective handles simultaneously. The other case, of trying to
+ // write the peer handle to a handle, doesn't make sense -- since no handle
+ // will be available to read the message from.)
+ for (size_t i = 0; i < transports->size(); i++) {
+ if (!(*transports)[i].is_valid())
+ continue;
+ if ((*transports)[i].GetType() == Dispatcher::kTypeMessagePipe) {
+ MessagePipeDispatcherTransport mp_transport((*transports)[i]);
+ if (mp_transport.GetMessagePipe() == this) {
+ // The other case should have been disallowed by |CoreImpl|. (Note:
+ // |port| is the peer port of the handle given to |WriteMessage()|.)
+ DCHECK_EQ(mp_transport.GetPort(), port);
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ }
+ }
}
-
- endpoints_[port]->EnqueueMessage(message, &replacement_dispatchers);
- } else {
- endpoints_[port]->EnqueueMessage(message, NULL);
}
- return MOJO_RESULT_OK;
+ return endpoints_[port]->EnqueueMessage(message, transports);
}
void MessagePipe::Attach(unsigned port,