OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ipc/mojo/ipc_channel_mojo.h" | 5 #include "ipc/mojo/ipc_channel_mojo.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
10 #include "ipc/ipc_listener.h" | 10 #include "ipc/ipc_listener.h" |
| 11 #include "ipc/mojo/ipc_channel_mojo_readers.h" |
11 #include "mojo/embedder/embedder.h" | 12 #include "mojo/embedder/embedder.h" |
12 | 13 |
13 #if defined(OS_POSIX) && !defined(OS_NACL) | 14 #if defined(OS_POSIX) && !defined(OS_NACL) |
14 #include "ipc/file_descriptor_set_posix.h" | 15 #include "ipc/file_descriptor_set_posix.h" |
15 #endif | 16 #endif |
16 | 17 |
17 namespace IPC { | 18 namespace IPC { |
18 | 19 |
19 namespace { | 20 namespace { |
20 | 21 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 const ChannelHandle& handle) { | 76 const ChannelHandle& handle) { |
76 #if defined(OS_POSIX) && !defined(OS_NACL) | 77 #if defined(OS_POSIX) && !defined(OS_NACL) |
77 return mojo::embedder::PlatformHandle(handle.socket.fd); | 78 return mojo::embedder::PlatformHandle(handle.socket.fd); |
78 #elif defined(OS_WIN) | 79 #elif defined(OS_WIN) |
79 return mojo::embedder::PlatformHandle(handle.pipe.handle); | 80 return mojo::embedder::PlatformHandle(handle.pipe.handle); |
80 #else | 81 #else |
81 #error "Unsupported Platform!" | 82 #error "Unsupported Platform!" |
82 #endif | 83 #endif |
83 } | 84 } |
84 | 85 |
85 //------------------------------------------------------------------------------ | |
86 | |
87 // TODO(morrita): This should be built using higher-level Mojo construct | |
88 // for clarity and extensibility. | |
89 class HelloMessage { | |
90 public: | |
91 static Pickle CreateRequest(int32 pid) { | |
92 Pickle request; | |
93 request.WriteString(kHelloRequestMagic); | |
94 request.WriteInt(pid); | |
95 return request; | |
96 } | |
97 | |
98 static bool ReadRequest(Pickle& pickle, int32* pid) { | |
99 PickleIterator iter(pickle); | |
100 std::string hello; | |
101 if (!iter.ReadString(&hello)) { | |
102 DLOG(WARNING) << "Failed to Read magic string."; | |
103 return false; | |
104 } | |
105 | |
106 if (hello != kHelloRequestMagic) { | |
107 DLOG(WARNING) << "Magic mismatch:" << hello; | |
108 return false; | |
109 } | |
110 | |
111 int read_pid; | |
112 if (!iter.ReadInt(&read_pid)) { | |
113 DLOG(WARNING) << "Failed to Read PID."; | |
114 return false; | |
115 } | |
116 | |
117 *pid = read_pid; | |
118 return true; | |
119 } | |
120 | |
121 static Pickle CreateResponse(int32 pid) { | |
122 Pickle request; | |
123 request.WriteString(kHelloResponseMagic); | |
124 request.WriteInt(pid); | |
125 return request; | |
126 } | |
127 | |
128 static bool ReadResponse(Pickle& pickle, int32* pid) { | |
129 PickleIterator iter(pickle); | |
130 std::string hello; | |
131 if (!iter.ReadString(&hello)) { | |
132 DLOG(WARNING) << "Failed to read magic string."; | |
133 return false; | |
134 } | |
135 | |
136 if (hello != kHelloResponseMagic) { | |
137 DLOG(WARNING) << "Magic mismatch:" << hello; | |
138 return false; | |
139 } | |
140 | |
141 int read_pid; | |
142 if (!iter.ReadInt(&read_pid)) { | |
143 DLOG(WARNING) << "Failed to read PID."; | |
144 return false; | |
145 } | |
146 | |
147 *pid = read_pid; | |
148 return true; | |
149 } | |
150 | |
151 private: | |
152 static const char* kHelloRequestMagic; | |
153 static const char* kHelloResponseMagic; | |
154 }; | |
155 | |
156 const char* HelloMessage::kHelloRequestMagic = "MREQ"; | |
157 const char* HelloMessage::kHelloResponseMagic = "MRES"; | |
158 | |
159 } // namespace | 86 } // namespace |
160 | 87 |
161 //------------------------------------------------------------------------------ | 88 //------------------------------------------------------------------------------ |
162 | 89 |
163 // A MessagePipeReader implemenation for IPC::Message communication. | |
164 class ChannelMojo::MessageReader : public internal::MessagePipeReader { | |
165 public: | |
166 MessageReader(mojo::ScopedMessagePipeHandle pipe, ChannelMojo* owner) | |
167 : internal::MessagePipeReader(pipe.Pass()), | |
168 owner_(owner) {} | |
169 | |
170 bool Send(scoped_ptr<Message> message); | |
171 virtual void OnMessageReceived() OVERRIDE; | |
172 virtual void OnPipeClosed() OVERRIDE; | |
173 virtual void OnPipeError(MojoResult error) OVERRIDE; | |
174 | |
175 private: | |
176 ChannelMojo* owner_; | |
177 }; | |
178 | |
179 void ChannelMojo::MessageReader::OnMessageReceived() { | |
180 Message message(data_buffer().empty() ? "" : &data_buffer()[0], | |
181 static_cast<uint32>(data_buffer().size())); | |
182 | |
183 std::vector<MojoHandle> handle_buffer; | |
184 TakeHandleBuffer(&handle_buffer); | |
185 #if defined(OS_POSIX) && !defined(OS_NACL) | |
186 for (size_t i = 0; i < handle_buffer.size(); ++i) { | |
187 mojo::embedder::ScopedPlatformHandle platform_handle; | |
188 MojoResult unwrap_result = mojo::embedder::PassWrappedPlatformHandle( | |
189 handle_buffer[i], &platform_handle); | |
190 if (unwrap_result != MOJO_RESULT_OK) { | |
191 DLOG(WARNING) << "Pipe failed to covert handles. Closing: " | |
192 << unwrap_result; | |
193 CloseWithError(unwrap_result); | |
194 return; | |
195 } | |
196 | |
197 bool ok = message.file_descriptor_set()->Add(platform_handle.release().fd); | |
198 DCHECK(ok); | |
199 } | |
200 #else | |
201 DCHECK(handle_buffer.empty()); | |
202 #endif | |
203 | |
204 message.TraceMessageEnd(); | |
205 owner_->OnMessageReceived(message); | |
206 } | |
207 | |
208 void ChannelMojo::MessageReader::OnPipeClosed() { | |
209 if (!owner_) | |
210 return; | |
211 owner_->OnPipeClosed(this); | |
212 owner_ = NULL; | |
213 } | |
214 | |
215 void ChannelMojo::MessageReader::OnPipeError(MojoResult error) { | |
216 if (!owner_) | |
217 return; | |
218 owner_->OnPipeError(this); | |
219 } | |
220 | |
221 bool ChannelMojo::MessageReader::Send(scoped_ptr<Message> message) { | |
222 DCHECK(IsValid()); | |
223 | |
224 message->TraceMessageBegin(); | |
225 std::vector<MojoHandle> handles; | |
226 #if defined(OS_POSIX) && !defined(OS_NACL) | |
227 // We dup() the handles in IPC::Message to transmit. | |
228 // IPC::FileDescriptorSet has intricate lifecycle semantics | |
229 // of FDs, so just to dup()-and-own them is the safest option. | |
230 if (message->HasFileDescriptors()) { | |
231 FileDescriptorSet* fdset = message->file_descriptor_set(); | |
232 for (size_t i = 0; i < fdset->size(); ++i) { | |
233 int fd_to_send = dup(fdset->GetDescriptorAt(i)); | |
234 if (-1 == fd_to_send) { | |
235 DPLOG(WARNING) << "Failed to dup FD to transmit."; | |
236 std::for_each(handles.begin(), handles.end(), &MojoClose); | |
237 CloseWithError(MOJO_RESULT_UNKNOWN); | |
238 return false; | |
239 } | |
240 | |
241 MojoHandle wrapped_handle; | |
242 MojoResult wrap_result = CreatePlatformHandleWrapper( | |
243 mojo::embedder::ScopedPlatformHandle( | |
244 mojo::embedder::PlatformHandle(fd_to_send)), | |
245 &wrapped_handle); | |
246 if (MOJO_RESULT_OK != wrap_result) { | |
247 DLOG(WARNING) << "Pipe failed to wrap handles. Closing: " | |
248 << wrap_result; | |
249 std::for_each(handles.begin(), handles.end(), &MojoClose); | |
250 CloseWithError(wrap_result); | |
251 return false; | |
252 } | |
253 | |
254 handles.push_back(wrapped_handle); | |
255 } | |
256 } | |
257 #endif | |
258 MojoResult write_result = MojoWriteMessage( | |
259 handle(), | |
260 message->data(), static_cast<uint32>(message->size()), | |
261 handles.empty() ? NULL : &handles[0], | |
262 static_cast<uint32>(handles.size()), | |
263 MOJO_WRITE_MESSAGE_FLAG_NONE); | |
264 if (MOJO_RESULT_OK != write_result) { | |
265 std::for_each(handles.begin(), handles.end(), &MojoClose); | |
266 CloseWithError(write_result); | |
267 return false; | |
268 } | |
269 | |
270 return true; | |
271 } | |
272 | |
273 //------------------------------------------------------------------------------ | |
274 | |
275 // MessagePipeReader implementation for control messages. | |
276 // Actual message handling is implemented by sublcasses. | |
277 class ChannelMojo::ControlReader : public internal::MessagePipeReader { | |
278 public: | |
279 ControlReader(mojo::ScopedMessagePipeHandle pipe, ChannelMojo* owner) | |
280 : internal::MessagePipeReader(pipe.Pass()), | |
281 owner_(owner) {} | |
282 | |
283 virtual bool Connect() { return true; } | |
284 virtual void OnPipeClosed() OVERRIDE; | |
285 virtual void OnPipeError(MojoResult error) OVERRIDE; | |
286 | |
287 protected: | |
288 ChannelMojo* owner_; | |
289 }; | |
290 | |
291 void ChannelMojo::ControlReader::OnPipeClosed() { | |
292 if (!owner_) | |
293 return; | |
294 owner_->OnPipeClosed(this); | |
295 owner_ = NULL; | |
296 } | |
297 | |
298 void ChannelMojo::ControlReader::OnPipeError(MojoResult error) { | |
299 if (!owner_) | |
300 return; | |
301 owner_->OnPipeError(this); | |
302 } | |
303 | |
304 //------------------------------------------------------------------------------ | |
305 | |
306 // ControlReader for server-side ChannelMojo. | |
307 class ChannelMojo::ServerControlReader : public ChannelMojo::ControlReader { | |
308 public: | |
309 ServerControlReader(mojo::ScopedMessagePipeHandle pipe, ChannelMojo* owner) | |
310 : ControlReader(pipe.Pass(), owner) { } | |
311 | |
312 virtual bool Connect() OVERRIDE; | |
313 virtual void OnMessageReceived() OVERRIDE; | |
314 | |
315 private: | |
316 MojoResult SendHelloRequest(); | |
317 MojoResult RespondHelloResponse(); | |
318 | |
319 mojo::ScopedMessagePipeHandle message_pipe_; | |
320 }; | |
321 | |
322 bool ChannelMojo::ServerControlReader::Connect() { | |
323 MojoResult result = SendHelloRequest(); | |
324 if (result != MOJO_RESULT_OK) { | |
325 CloseWithError(result); | |
326 return false; | |
327 } | |
328 | |
329 return true; | |
330 } | |
331 | |
332 MojoResult ChannelMojo::ServerControlReader::SendHelloRequest() { | |
333 DCHECK(IsValid()); | |
334 DCHECK(!message_pipe_.is_valid()); | |
335 | |
336 mojo::ScopedMessagePipeHandle self; | |
337 mojo::ScopedMessagePipeHandle peer; | |
338 MojoResult create_result = mojo::CreateMessagePipe( | |
339 NULL, &message_pipe_, &peer); | |
340 if (MOJO_RESULT_OK != create_result) { | |
341 DLOG(WARNING) << "mojo::CreateMessagePipe failed: " << create_result; | |
342 return create_result; | |
343 } | |
344 | |
345 MojoHandle peer_to_send = peer.get().value(); | |
346 Pickle request = HelloMessage::CreateRequest(owner_->GetSelfPID()); | |
347 MojoResult write_result = MojoWriteMessage( | |
348 handle(), | |
349 request.data(), static_cast<uint32>(request.size()), | |
350 &peer_to_send, 1, | |
351 MOJO_WRITE_MESSAGE_FLAG_NONE); | |
352 if (MOJO_RESULT_OK != write_result) { | |
353 DLOG(WARNING) << "Writing Hello request failed: " << create_result; | |
354 return write_result; | |
355 } | |
356 | |
357 // |peer| is sent and no longer owned by |this|. | |
358 (void)peer.release(); | |
359 return MOJO_RESULT_OK; | |
360 } | |
361 | |
362 MojoResult ChannelMojo::ServerControlReader::RespondHelloResponse() { | |
363 Pickle request(data_buffer().empty() ? "" : &data_buffer()[0], | |
364 static_cast<uint32>(data_buffer().size())); | |
365 | |
366 int32 read_pid = 0; | |
367 if (!HelloMessage::ReadResponse(request, &read_pid)) { | |
368 DLOG(ERROR) << "Failed to parse Hello response."; | |
369 return MOJO_RESULT_UNKNOWN; | |
370 } | |
371 | |
372 base::ProcessId pid = static_cast<base::ProcessId>(read_pid); | |
373 owner_->set_peer_pid(pid); | |
374 owner_->OnConnected(message_pipe_.Pass()); | |
375 return MOJO_RESULT_OK; | |
376 } | |
377 | |
378 void ChannelMojo::ServerControlReader::OnMessageReceived() { | |
379 MojoResult result = RespondHelloResponse(); | |
380 if (result != MOJO_RESULT_OK) | |
381 CloseWithError(result); | |
382 } | |
383 | |
384 //------------------------------------------------------------------------------ | |
385 | |
386 // ControlReader for client-side ChannelMojo. | |
387 class ChannelMojo::ClientControlReader : public ChannelMojo::ControlReader { | |
388 public: | |
389 ClientControlReader(mojo::ScopedMessagePipeHandle pipe, ChannelMojo* owner) | |
390 : ControlReader(pipe.Pass(), owner) {} | |
391 | |
392 virtual void OnMessageReceived() OVERRIDE; | |
393 | |
394 private: | |
395 MojoResult RespondHelloRequest(MojoHandle message_channel); | |
396 }; | |
397 | |
398 MojoResult ChannelMojo::ClientControlReader::RespondHelloRequest( | |
399 MojoHandle message_channel) { | |
400 DCHECK(IsValid()); | |
401 | |
402 mojo::ScopedMessagePipeHandle received_pipe( | |
403 (mojo::MessagePipeHandle(message_channel))); | |
404 | |
405 int32 read_request = 0; | |
406 Pickle request(data_buffer().empty() ? "" : &data_buffer()[0], | |
407 static_cast<uint32>(data_buffer().size())); | |
408 if (!HelloMessage::ReadRequest(request, &read_request)) { | |
409 DLOG(ERROR) << "Hello request has wrong magic."; | |
410 return MOJO_RESULT_UNKNOWN; | |
411 } | |
412 | |
413 base::ProcessId pid = read_request; | |
414 Pickle response = HelloMessage::CreateResponse(owner_->GetSelfPID()); | |
415 MojoResult write_result = MojoWriteMessage( | |
416 handle(), | |
417 response.data(), static_cast<uint32>(response.size()), | |
418 NULL, 0, | |
419 MOJO_WRITE_MESSAGE_FLAG_NONE); | |
420 if (MOJO_RESULT_OK != write_result) { | |
421 DLOG(ERROR) << "Writing Hello response failed: " << write_result; | |
422 return write_result; | |
423 } | |
424 | |
425 owner_->set_peer_pid(pid); | |
426 owner_->OnConnected(received_pipe.Pass()); | |
427 return MOJO_RESULT_OK; | |
428 } | |
429 | |
430 void ChannelMojo::ClientControlReader::OnMessageReceived() { | |
431 std::vector<MojoHandle> handle_buffer; | |
432 TakeHandleBuffer(&handle_buffer); | |
433 if (handle_buffer.size() != 1) { | |
434 DLOG(ERROR) << "Hello request doesn't contains required handle: " | |
435 << handle_buffer.size(); | |
436 CloseWithError(MOJO_RESULT_UNKNOWN); | |
437 return; | |
438 } | |
439 | |
440 MojoResult result = RespondHelloRequest(handle_buffer[0]); | |
441 if (result != MOJO_RESULT_OK) { | |
442 DLOG(ERROR) << "Failed to respond Hello request. Closing: " | |
443 << result; | |
444 CloseWithError(result); | |
445 } | |
446 } | |
447 | |
448 //------------------------------------------------------------------------------ | |
449 | |
450 void ChannelMojo::ChannelInfoDeleter::operator()( | 90 void ChannelMojo::ChannelInfoDeleter::operator()( |
451 mojo::embedder::ChannelInfo* ptr) const { | 91 mojo::embedder::ChannelInfo* ptr) const { |
452 mojo::embedder::DestroyChannelOnIOThread(ptr); | 92 mojo::embedder::DestroyChannelOnIOThread(ptr); |
453 } | 93 } |
454 | 94 |
455 //------------------------------------------------------------------------------ | 95 //------------------------------------------------------------------------------ |
456 | 96 |
457 // static | 97 // static |
458 scoped_ptr<ChannelMojo> ChannelMojo::Create( | 98 scoped_ptr<ChannelMojo> ChannelMojo::Create( |
459 const ChannelHandle &channel_handle, Mode mode, Listener* listener, | 99 const ChannelHandle &channel_handle, Mode mode, Listener* listener, |
460 scoped_refptr<base::TaskRunner> io_thread_task_runner) { | 100 scoped_refptr<base::TaskRunner> io_thread_task_runner) { |
461 return make_scoped_ptr(new ChannelMojo( | 101 return make_scoped_ptr( |
462 Channel::Create(channel_handle, mode, g_null_listener.Pointer()), | 102 new ChannelMojo(channel_handle, mode, listener, io_thread_task_runner)); |
463 mode, listener, io_thread_task_runner)); | |
464 } | 103 } |
465 | 104 |
466 // static | 105 // static |
467 scoped_ptr<ChannelFactory> ChannelMojo::CreateFactory( | 106 scoped_ptr<ChannelFactory> ChannelMojo::CreateFactory( |
468 const ChannelHandle &channel_handle, Mode mode, | 107 const ChannelHandle &channel_handle, Mode mode, |
469 scoped_refptr<base::TaskRunner> io_thread_task_runner) { | 108 scoped_refptr<base::TaskRunner> io_thread_task_runner) { |
470 return make_scoped_ptr( | 109 return make_scoped_ptr( |
471 new MojoChannelFactory( | 110 new MojoChannelFactory( |
472 channel_handle, mode, | 111 channel_handle, mode, |
473 io_thread_task_runner)).PassAs<ChannelFactory>(); | 112 io_thread_task_runner)).PassAs<ChannelFactory>(); |
474 } | 113 } |
475 | 114 |
476 ChannelMojo::ChannelMojo( | 115 ChannelMojo::ChannelMojo(const ChannelHandle& channel_handle, |
477 scoped_ptr<Channel> bootstrap, Mode mode, Listener* listener, | 116 Mode mode, |
478 scoped_refptr<base::TaskRunner> io_thread_task_runner) | 117 Listener* listener, |
479 : bootstrap_(bootstrap.Pass()), | 118 scoped_refptr<base::TaskRunner> io_thread_task_runner) |
480 mode_(mode), listener_(listener), | 119 : bootstrap_( |
| 120 Channel::Create(channel_handle, mode, g_null_listener.Pointer())), |
| 121 mode_(mode), |
| 122 listener_(listener), |
481 peer_pid_(base::kNullProcessId), | 123 peer_pid_(base::kNullProcessId), |
482 weak_factory_(this) { | 124 weak_factory_(this) { |
483 if (base::MessageLoopProxy::current() == io_thread_task_runner.get()) { | 125 if (base::MessageLoopProxy::current() == io_thread_task_runner.get()) { |
484 InitOnIOThread(); | 126 InitOnIOThread(); |
485 } else { | 127 } else { |
486 io_thread_task_runner->PostTask(FROM_HERE, | 128 io_thread_task_runner->PostTask(FROM_HERE, |
487 base::Bind(&ChannelMojo::InitOnIOThread, | 129 base::Bind(&ChannelMojo::InitOnIOThread, |
488 weak_factory_.GetWeakPtr())); | 130 weak_factory_.GetWeakPtr())); |
489 } | 131 } |
490 } | 132 } |
491 | 133 |
492 ChannelMojo::~ChannelMojo() { | 134 ChannelMojo::~ChannelMojo() { |
493 Close(); | 135 Close(); |
494 } | 136 } |
495 | 137 |
496 void ChannelMojo::InitOnIOThread() { | 138 void ChannelMojo::InitOnIOThread() { |
497 mojo::embedder::ChannelInfo* channel_info; | 139 mojo::embedder::ChannelInfo* channel_info; |
498 mojo::ScopedMessagePipeHandle control_pipe = | 140 mojo::ScopedMessagePipeHandle control_pipe = |
499 mojo::embedder::CreateChannelOnIOThread( | 141 mojo::embedder::CreateChannelOnIOThread( |
500 mojo::embedder::ScopedPlatformHandle( | 142 mojo::embedder::ScopedPlatformHandle( |
501 ToPlatformHandle(bootstrap_->TakePipeHandle())), | 143 ToPlatformHandle(bootstrap_->TakePipeHandle())), |
502 &channel_info); | 144 &channel_info); |
503 channel_info_.reset(channel_info); | 145 channel_info_.reset(channel_info); |
504 | 146 |
505 switch (mode_) { | 147 switch (mode_) { |
506 case MODE_SERVER: | 148 case MODE_SERVER: |
507 control_reader_.reset(new ServerControlReader(control_pipe.Pass(), this)); | 149 control_reader_.reset( |
| 150 new internal::ServerControlReader(control_pipe.Pass(), this)); |
508 break; | 151 break; |
509 case MODE_CLIENT: | 152 case MODE_CLIENT: |
510 control_reader_.reset(new ClientControlReader(control_pipe.Pass(), this)); | 153 control_reader_.reset( |
| 154 new internal::ClientControlReader(control_pipe.Pass(), this)); |
511 break; | 155 break; |
512 default: | 156 default: |
513 NOTREACHED(); | 157 NOTREACHED(); |
514 break; | 158 break; |
515 } | 159 } |
516 } | 160 } |
517 | 161 |
518 bool ChannelMojo::Connect() { | 162 bool ChannelMojo::Connect() { |
519 DCHECK(!message_reader_); | 163 DCHECK(!message_reader_); |
520 return control_reader_->Connect(); | 164 return control_reader_->Connect(); |
521 } | 165 } |
522 | 166 |
523 void ChannelMojo::Close() { | 167 void ChannelMojo::Close() { |
524 control_reader_.reset(); | 168 control_reader_.reset(); |
525 message_reader_.reset(); | 169 message_reader_.reset(); |
526 channel_info_.reset(); | 170 channel_info_.reset(); |
527 } | 171 } |
528 | 172 |
529 void ChannelMojo::OnConnected(mojo::ScopedMessagePipeHandle pipe) { | 173 void ChannelMojo::OnConnected(mojo::ScopedMessagePipeHandle pipe) { |
530 message_reader_ = make_scoped_ptr(new MessageReader(pipe.Pass(), this)); | 174 message_reader_ = |
| 175 make_scoped_ptr(new internal::MessageReader(pipe.Pass(), this)); |
531 | 176 |
532 for (size_t i = 0; i < pending_messages_.size(); ++i) { | 177 for (size_t i = 0; i < pending_messages_.size(); ++i) { |
533 message_reader_->Send(make_scoped_ptr(pending_messages_[i])); | 178 message_reader_->Send(make_scoped_ptr(pending_messages_[i])); |
534 pending_messages_[i] = NULL; | 179 pending_messages_[i] = NULL; |
535 } | 180 } |
536 | 181 |
537 pending_messages_.clear(); | 182 pending_messages_.clear(); |
538 | 183 |
539 listener_->OnChannelConnected(GetPeerPID()); | 184 listener_->OnChannelConnected(GetPeerPID()); |
540 } | 185 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 } | 221 } |
577 | 222 |
578 #if defined(OS_POSIX) && !defined(OS_NACL) | 223 #if defined(OS_POSIX) && !defined(OS_NACL) |
579 int ChannelMojo::GetClientFileDescriptor() const { | 224 int ChannelMojo::GetClientFileDescriptor() const { |
580 return bootstrap_->GetClientFileDescriptor(); | 225 return bootstrap_->GetClientFileDescriptor(); |
581 } | 226 } |
582 | 227 |
583 int ChannelMojo::TakeClientFileDescriptor() { | 228 int ChannelMojo::TakeClientFileDescriptor() { |
584 return bootstrap_->TakeClientFileDescriptor(); | 229 return bootstrap_->TakeClientFileDescriptor(); |
585 } | 230 } |
| 231 |
| 232 // static |
| 233 MojoResult ChannelMojo::WriteToFileDescriptorSet( |
| 234 const std::vector<MojoHandle>& handle_buffer, |
| 235 Message* message) { |
| 236 for (size_t i = 0; i < handle_buffer.size(); ++i) { |
| 237 mojo::embedder::ScopedPlatformHandle platform_handle; |
| 238 MojoResult unwrap_result = mojo::embedder::PassWrappedPlatformHandle( |
| 239 handle_buffer[i], &platform_handle); |
| 240 if (unwrap_result != MOJO_RESULT_OK) { |
| 241 DLOG(WARNING) << "Pipe failed to covert handles. Closing: " |
| 242 << unwrap_result; |
| 243 return unwrap_result; |
| 244 } |
| 245 |
| 246 bool ok = message->file_descriptor_set()->Add(platform_handle.release().fd); |
| 247 DCHECK(ok); |
| 248 } |
| 249 |
| 250 return MOJO_RESULT_OK; |
| 251 } |
| 252 |
| 253 // static |
| 254 MojoResult ChannelMojo::ReadFromFileDescriptorSet( |
| 255 const Message& message, |
| 256 std::vector<MojoHandle>* handles) { |
| 257 // We dup() the handles in IPC::Message to transmit. |
| 258 // IPC::FileDescriptorSet has intricate lifecycle semantics |
| 259 // of FDs, so just to dup()-and-own them is the safest option. |
| 260 if (message.HasFileDescriptors()) { |
| 261 const FileDescriptorSet* fdset = message.file_descriptor_set(); |
| 262 for (size_t i = 0; i < fdset->size(); ++i) { |
| 263 int fd_to_send = dup(fdset->GetDescriptorAt(i)); |
| 264 if (-1 == fd_to_send) { |
| 265 DPLOG(WARNING) << "Failed to dup FD to transmit."; |
| 266 return MOJO_RESULT_UNKNOWN; |
| 267 } |
| 268 |
| 269 MojoHandle wrapped_handle; |
| 270 MojoResult wrap_result = CreatePlatformHandleWrapper( |
| 271 mojo::embedder::ScopedPlatformHandle( |
| 272 mojo::embedder::PlatformHandle(fd_to_send)), |
| 273 &wrapped_handle); |
| 274 if (MOJO_RESULT_OK != wrap_result) { |
| 275 DLOG(WARNING) << "Pipe failed to wrap handles. Closing: " |
| 276 << wrap_result; |
| 277 return wrap_result; |
| 278 } |
| 279 |
| 280 handles->push_back(wrapped_handle); |
| 281 } |
| 282 } |
| 283 |
| 284 return MOJO_RESULT_OK; |
| 285 } |
| 286 |
586 #endif // defined(OS_POSIX) && !defined(OS_NACL) | 287 #endif // defined(OS_POSIX) && !defined(OS_NACL) |
587 | 288 |
588 } // namespace IPC | 289 } // namespace IPC |
OLD | NEW |