Home | History | Annotate | Download | only in mojo
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ipc/mojo/ipc_channel_mojo_readers.h"
      6 
      7 #include "ipc/mojo/ipc_channel_mojo.h"
      8 #include "mojo/embedder/embedder.h"
      9 
     10 #if defined(OS_POSIX) && !defined(OS_NACL)
     11 #include "ipc/file_descriptor_set_posix.h"
     12 #endif
     13 
     14 namespace IPC {
     15 namespace internal {
     16 
     17 namespace {
     18 
     19 // TODO(morrita): This should be built using higher-level Mojo construct
     20 // for clarity and extensibility.
     21 class HelloMessage {
     22  public:
     23   static Pickle CreateRequest(int32 pid) {
     24     Pickle request;
     25     request.WriteString(kHelloRequestMagic);
     26     request.WriteInt(pid);
     27     return request;
     28   }
     29 
     30   static bool ReadRequest(Pickle& pickle, int32* pid) {
     31     PickleIterator iter(pickle);
     32     std::string hello;
     33     if (!iter.ReadString(&hello)) {
     34       DLOG(WARNING) << "Failed to Read magic string.";
     35       return false;
     36     }
     37 
     38     if (hello != kHelloRequestMagic) {
     39       DLOG(WARNING) << "Magic mismatch:" << hello;
     40       return false;
     41     }
     42 
     43     int read_pid;
     44     if (!iter.ReadInt(&read_pid)) {
     45       DLOG(WARNING) << "Failed to Read PID.";
     46       return false;
     47     }
     48 
     49     *pid = read_pid;
     50     return true;
     51   }
     52 
     53   static Pickle CreateResponse(int32 pid) {
     54     Pickle request;
     55     request.WriteString(kHelloResponseMagic);
     56     request.WriteInt(pid);
     57     return request;
     58   }
     59 
     60   static bool ReadResponse(Pickle& pickle, int32* pid) {
     61     PickleIterator iter(pickle);
     62     std::string hello;
     63     if (!iter.ReadString(&hello)) {
     64       DLOG(WARNING) << "Failed to read magic string.";
     65       return false;
     66     }
     67 
     68     if (hello != kHelloResponseMagic) {
     69       DLOG(WARNING) << "Magic mismatch:" << hello;
     70       return false;
     71     }
     72 
     73     int read_pid;
     74     if (!iter.ReadInt(&read_pid)) {
     75       DLOG(WARNING) << "Failed to read PID.";
     76       return false;
     77     }
     78 
     79     *pid = read_pid;
     80     return true;
     81   }
     82 
     83  private:
     84   static const char* kHelloRequestMagic;
     85   static const char* kHelloResponseMagic;
     86 };
     87 
     88 const char* HelloMessage::kHelloRequestMagic = "MREQ";
     89 const char* HelloMessage::kHelloResponseMagic = "MRES";
     90 
     91 }  // namespace
     92 
     93 //------------------------------------------------------------------------------
     94 
     95 MessageReader::MessageReader(mojo::ScopedMessagePipeHandle pipe,
     96                              ChannelMojo* owner)
     97     : internal::MessagePipeReader(pipe.Pass()), owner_(owner) {
     98 }
     99 
    100 void MessageReader::OnMessageReceived() {
    101   Message message(data_buffer().empty() ? "" : &data_buffer()[0],
    102                   static_cast<uint32>(data_buffer().size()));
    103 
    104   std::vector<MojoHandle> handle_buffer;
    105   TakeHandleBuffer(&handle_buffer);
    106 #if defined(OS_POSIX) && !defined(OS_NACL)
    107   MojoResult write_result =
    108       ChannelMojo::WriteToFileDescriptorSet(handle_buffer, &message);
    109   if (write_result != MOJO_RESULT_OK) {
    110     CloseWithError(write_result);
    111     return;
    112   }
    113 #else
    114   DCHECK(handle_buffer.empty());
    115 #endif
    116 
    117   message.TraceMessageEnd();
    118   owner_->OnMessageReceived(message);
    119 }
    120 
    121 void MessageReader::OnPipeClosed() {
    122   if (!owner_)
    123     return;
    124   owner_->OnPipeClosed(this);
    125   owner_ = NULL;
    126 }
    127 
    128 void MessageReader::OnPipeError(MojoResult error) {
    129   if (!owner_)
    130     return;
    131   owner_->OnPipeError(this);
    132 }
    133 
    134 bool MessageReader::Send(scoped_ptr<Message> message) {
    135   DCHECK(IsValid());
    136 
    137   message->TraceMessageBegin();
    138   std::vector<MojoHandle> handles;
    139 #if defined(OS_POSIX) && !defined(OS_NACL)
    140   MojoResult read_result =
    141       ChannelMojo::ReadFromFileDescriptorSet(message.get(), &handles);
    142   if (read_result != MOJO_RESULT_OK) {
    143     std::for_each(handles.begin(), handles.end(), &MojoClose);
    144     CloseWithError(read_result);
    145     return false;
    146   }
    147 #endif
    148   MojoResult write_result =
    149       MojoWriteMessage(handle(),
    150                        message->data(),
    151                        static_cast<uint32>(message->size()),
    152                        handles.empty() ? NULL : &handles[0],
    153                        static_cast<uint32>(handles.size()),
    154                        MOJO_WRITE_MESSAGE_FLAG_NONE);
    155   if (MOJO_RESULT_OK != write_result) {
    156     std::for_each(handles.begin(), handles.end(), &MojoClose);
    157     CloseWithError(write_result);
    158     return false;
    159   }
    160 
    161   return true;
    162 }
    163 
    164 //------------------------------------------------------------------------------
    165 
    166 ControlReader::ControlReader(mojo::ScopedMessagePipeHandle pipe,
    167                              ChannelMojo* owner)
    168     : internal::MessagePipeReader(pipe.Pass()), owner_(owner) {
    169 }
    170 
    171 void ControlReader::OnPipeClosed() {
    172   if (!owner_)
    173     return;
    174   owner_->OnPipeClosed(this);
    175   owner_ = NULL;
    176 }
    177 
    178 void ControlReader::OnPipeError(MojoResult error) {
    179   if (!owner_)
    180     return;
    181   owner_->OnPipeError(this);
    182 }
    183 
    184 bool ControlReader::Connect() {
    185   return true;
    186 }
    187 
    188 //------------------------------------------------------------------------------
    189 
    190 ServerControlReader::ServerControlReader(mojo::ScopedMessagePipeHandle pipe,
    191                                          ChannelMojo* owner)
    192     : ControlReader(pipe.Pass(), owner) {
    193 }
    194 
    195 ServerControlReader::~ServerControlReader() {
    196 }
    197 
    198 bool ServerControlReader::Connect() {
    199   MojoResult result = SendHelloRequest();
    200   if (result != MOJO_RESULT_OK) {
    201     CloseWithError(result);
    202     return false;
    203   }
    204 
    205   return true;
    206 }
    207 
    208 MojoResult ServerControlReader::SendHelloRequest() {
    209   DCHECK(IsValid());
    210   DCHECK(!message_pipe_.is_valid());
    211 
    212   mojo::ScopedMessagePipeHandle self;
    213   mojo::ScopedMessagePipeHandle peer;
    214   MojoResult create_result =
    215       mojo::CreateMessagePipe(NULL, &message_pipe_, &peer);
    216   if (MOJO_RESULT_OK != create_result) {
    217     DLOG(WARNING) << "mojo::CreateMessagePipe failed: " << create_result;
    218     return create_result;
    219   }
    220 
    221   MojoHandle peer_to_send = peer.get().value();
    222   Pickle request = HelloMessage::CreateRequest(owner_->GetSelfPID());
    223   MojoResult write_result =
    224       MojoWriteMessage(handle(),
    225                        request.data(),
    226                        static_cast<uint32>(request.size()),
    227                        &peer_to_send,
    228                        1,
    229                        MOJO_WRITE_MESSAGE_FLAG_NONE);
    230   if (MOJO_RESULT_OK != write_result) {
    231     DLOG(WARNING) << "Writing Hello request failed: " << create_result;
    232     return write_result;
    233   }
    234 
    235   // |peer| is sent and no longer owned by |this|.
    236   (void)peer.release();
    237   return MOJO_RESULT_OK;
    238 }
    239 
    240 MojoResult ServerControlReader::RespondHelloResponse() {
    241   Pickle request(data_buffer().empty() ? "" : &data_buffer()[0],
    242                  static_cast<uint32>(data_buffer().size()));
    243 
    244   int32 read_pid = 0;
    245   if (!HelloMessage::ReadResponse(request, &read_pid)) {
    246     DLOG(ERROR) << "Failed to parse Hello response.";
    247     return MOJO_RESULT_UNKNOWN;
    248   }
    249 
    250   base::ProcessId pid = static_cast<base::ProcessId>(read_pid);
    251   owner_->set_peer_pid(pid);
    252   owner_->OnConnected(message_pipe_.Pass());
    253   return MOJO_RESULT_OK;
    254 }
    255 
    256 void ServerControlReader::OnMessageReceived() {
    257   MojoResult result = RespondHelloResponse();
    258   if (result != MOJO_RESULT_OK)
    259     CloseWithError(result);
    260 }
    261 
    262 //------------------------------------------------------------------------------
    263 
    264 ClientControlReader::ClientControlReader(mojo::ScopedMessagePipeHandle pipe,
    265                                          ChannelMojo* owner)
    266     : ControlReader(pipe.Pass(), owner) {
    267 }
    268 
    269 MojoResult ClientControlReader::RespondHelloRequest(
    270     MojoHandle message_channel) {
    271   DCHECK(IsValid());
    272 
    273   mojo::ScopedMessagePipeHandle received_pipe(
    274       (mojo::MessagePipeHandle(message_channel)));
    275 
    276   int32 read_request = 0;
    277   Pickle request(data_buffer().empty() ? "" : &data_buffer()[0],
    278                  static_cast<uint32>(data_buffer().size()));
    279   if (!HelloMessage::ReadRequest(request, &read_request)) {
    280     DLOG(ERROR) << "Hello request has wrong magic.";
    281     return MOJO_RESULT_UNKNOWN;
    282   }
    283 
    284   base::ProcessId pid = read_request;
    285   Pickle response = HelloMessage::CreateResponse(owner_->GetSelfPID());
    286   MojoResult write_result =
    287       MojoWriteMessage(handle(),
    288                        response.data(),
    289                        static_cast<uint32>(response.size()),
    290                        NULL,
    291                        0,
    292                        MOJO_WRITE_MESSAGE_FLAG_NONE);
    293   if (MOJO_RESULT_OK != write_result) {
    294     DLOG(ERROR) << "Writing Hello response failed: " << write_result;
    295     return write_result;
    296   }
    297 
    298   owner_->set_peer_pid(pid);
    299   owner_->OnConnected(received_pipe.Pass());
    300   return MOJO_RESULT_OK;
    301 }
    302 
    303 void ClientControlReader::OnMessageReceived() {
    304   std::vector<MojoHandle> handle_buffer;
    305   TakeHandleBuffer(&handle_buffer);
    306   if (handle_buffer.size() != 1) {
    307     DLOG(ERROR) << "Hello request doesn't contains required handle: "
    308                 << handle_buffer.size();
    309     CloseWithError(MOJO_RESULT_UNKNOWN);
    310     return;
    311   }
    312 
    313   MojoResult result = RespondHelloRequest(handle_buffer[0]);
    314   if (result != MOJO_RESULT_OK) {
    315     DLOG(ERROR) << "Failed to respond Hello request. Closing: " << result;
    316     CloseWithError(result);
    317   }
    318 }
    319 
    320 }  // namespace internal
    321 }  // namespace IPC
    322