• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
CreateRequest(int32 pid)23   static Pickle CreateRequest(int32 pid) {
24     Pickle request;
25     request.WriteString(kHelloRequestMagic);
26     request.WriteInt(pid);
27     return request;
28   }
29 
ReadRequest(Pickle & pickle,int32 * pid)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 
CreateResponse(int32 pid)53   static Pickle CreateResponse(int32 pid) {
54     Pickle request;
55     request.WriteString(kHelloResponseMagic);
56     request.WriteInt(pid);
57     return request;
58   }
59 
ReadResponse(Pickle & pickle,int32 * pid)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 
MessageReader(mojo::ScopedMessagePipeHandle pipe,ChannelMojo * owner)95 MessageReader::MessageReader(mojo::ScopedMessagePipeHandle pipe,
96                              ChannelMojo* owner)
97     : internal::MessagePipeReader(pipe.Pass()), owner_(owner) {
98 }
99 
OnMessageReceived()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 
OnPipeClosed()121 void MessageReader::OnPipeClosed() {
122   if (!owner_)
123     return;
124   owner_->OnPipeClosed(this);
125   owner_ = NULL;
126 }
127 
OnPipeError(MojoResult error)128 void MessageReader::OnPipeError(MojoResult error) {
129   if (!owner_)
130     return;
131   owner_->OnPipeError(this);
132 }
133 
Send(scoped_ptr<Message> message)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 
ControlReader(mojo::ScopedMessagePipeHandle pipe,ChannelMojo * owner)166 ControlReader::ControlReader(mojo::ScopedMessagePipeHandle pipe,
167                              ChannelMojo* owner)
168     : internal::MessagePipeReader(pipe.Pass()), owner_(owner) {
169 }
170 
OnPipeClosed()171 void ControlReader::OnPipeClosed() {
172   if (!owner_)
173     return;
174   owner_->OnPipeClosed(this);
175   owner_ = NULL;
176 }
177 
OnPipeError(MojoResult error)178 void ControlReader::OnPipeError(MojoResult error) {
179   if (!owner_)
180     return;
181   owner_->OnPipeError(this);
182 }
183 
Connect()184 bool ControlReader::Connect() {
185   return true;
186 }
187 
188 //------------------------------------------------------------------------------
189 
ServerControlReader(mojo::ScopedMessagePipeHandle pipe,ChannelMojo * owner)190 ServerControlReader::ServerControlReader(mojo::ScopedMessagePipeHandle pipe,
191                                          ChannelMojo* owner)
192     : ControlReader(pipe.Pass(), owner) {
193 }
194 
~ServerControlReader()195 ServerControlReader::~ServerControlReader() {
196 }
197 
Connect()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 
SendHelloRequest()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 
RespondHelloResponse()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 
OnMessageReceived()256 void ServerControlReader::OnMessageReceived() {
257   MojoResult result = RespondHelloResponse();
258   if (result != MOJO_RESULT_OK)
259     CloseWithError(result);
260 }
261 
262 //------------------------------------------------------------------------------
263 
ClientControlReader(mojo::ScopedMessagePipeHandle pipe,ChannelMojo * owner)264 ClientControlReader::ClientControlReader(mojo::ScopedMessagePipeHandle pipe,
265                                          ChannelMojo* owner)
266     : ControlReader(pipe.Pass(), owner) {
267 }
268 
RespondHelloRequest(MojoHandle message_channel)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 
OnMessageReceived()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