OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "mojo/edk/system/raw_channel.h" | 5 #include "mojo/edk/system/raw_channel.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <sys/uio.h> | 8 #include <sys/uio.h> |
9 #include <unistd.h> | 9 #include <unistd.h> |
10 | 10 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 platform_handles->size() > embedder::kPlatformChannelMaxNumHandles) { | 128 platform_handles->size() > embedder::kPlatformChannelMaxNumHandles) { |
129 // We can't attach all the FDs to a single message, so we have to "split" | 129 // We can't attach all the FDs to a single message, so we have to "split" |
130 // the message. Send as many control messages as needed first with FDs | 130 // the message. Send as many control messages as needed first with FDs |
131 // attached (and no data). | 131 // attached (and no data). |
132 size_t i = 0; | 132 size_t i = 0; |
133 for (; platform_handles->size() - i > | 133 for (; platform_handles->size() - i > |
134 embedder::kPlatformChannelMaxNumHandles; | 134 embedder::kPlatformChannelMaxNumHandles; |
135 i += embedder::kPlatformChannelMaxNumHandles) { | 135 i += embedder::kPlatformChannelMaxNumHandles) { |
136 scoped_ptr<MessageInTransit> fd_message(new MessageInTransit( | 136 scoped_ptr<MessageInTransit> fd_message(new MessageInTransit( |
137 MessageInTransit::kTypeRawChannel, | 137 MessageInTransit::kTypeRawChannel, |
138 MessageInTransit::kSubtypeRawChannelPosixExtraPlatformHandles, | 138 MessageInTransit::kSubtypeRawChannelPosixExtraPlatformHandles, 0, |
139 0, | |
140 nullptr)); | 139 nullptr)); |
141 embedder::ScopedPlatformHandleVectorPtr fds( | 140 embedder::ScopedPlatformHandleVectorPtr fds( |
142 new embedder::PlatformHandleVector( | 141 new embedder::PlatformHandleVector( |
143 platform_handles->begin() + i, | 142 platform_handles->begin() + i, |
144 platform_handles->begin() + i + | 143 platform_handles->begin() + i + |
145 embedder::kPlatformChannelMaxNumHandles)); | 144 embedder::kPlatformChannelMaxNumHandles)); |
146 fd_message->SetTransportData( | 145 fd_message->SetTransportData( |
147 make_scoped_ptr(new TransportData(fds.Pass()))); | 146 make_scoped_ptr(new TransportData(fds.Pass()))); |
148 RawChannel::EnqueueMessageNoLock(fd_message.Pass()); | 147 RawChannel::EnqueueMessageNoLock(fd_message.Pass()); |
149 } | 148 } |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 write_result = embedder::PlatformChannelSendmsgWithHandles( | 245 write_result = embedder::PlatformChannelSendmsgWithHandles( |
247 fd_.get(), iov, buffer_count, platform_handles, num_platform_handles); | 246 fd_.get(), iov, buffer_count, platform_handles, num_platform_handles); |
248 for (size_t i = 0; i < num_platform_handles; i++) | 247 for (size_t i = 0; i < num_platform_handles; i++) |
249 platform_handles[i].CloseIfNecessary(); | 248 platform_handles[i].CloseIfNecessary(); |
250 } else { | 249 } else { |
251 std::vector<WriteBuffer::Buffer> buffers; | 250 std::vector<WriteBuffer::Buffer> buffers; |
252 write_buffer_no_lock()->GetBuffers(&buffers); | 251 write_buffer_no_lock()->GetBuffers(&buffers); |
253 DCHECK(!buffers.empty()); | 252 DCHECK(!buffers.empty()); |
254 | 253 |
255 if (buffers.size() == 1) { | 254 if (buffers.size() == 1) { |
256 write_result = embedder::PlatformChannelWrite( | 255 write_result = embedder::PlatformChannelWrite(fd_.get(), buffers[0].addr, |
257 fd_.get(), buffers[0].addr, buffers[0].size); | 256 buffers[0].size); |
258 } else { | 257 } else { |
259 const size_t kMaxBufferCount = 10; | 258 const size_t kMaxBufferCount = 10; |
260 iovec iov[kMaxBufferCount]; | 259 iovec iov[kMaxBufferCount]; |
261 size_t buffer_count = std::min(buffers.size(), kMaxBufferCount); | 260 size_t buffer_count = std::min(buffers.size(), kMaxBufferCount); |
262 for (size_t i = 0; i < buffer_count; ++i) { | 261 for (size_t i = 0; i < buffer_count; ++i) { |
263 iov[i].iov_base = const_cast<char*>(buffers[i].addr); | 262 iov[i].iov_base = const_cast<char*>(buffers[i].addr); |
264 iov[i].iov_len = buffers[i].size; | 263 iov[i].iov_len = buffers[i].size; |
265 } | 264 } |
266 | 265 |
267 write_result = | 266 write_result = |
(...skipping 27 matching lines...) Expand all Loading... |
295 // If we're not on the I/O thread, we have to post a task to do this. | 294 // If we're not on the I/O thread, we have to post a task to do this. |
296 if (base::MessageLoop::current() != message_loop_for_io()) { | 295 if (base::MessageLoop::current() != message_loop_for_io()) { |
297 message_loop_for_io()->PostTask(FROM_HERE, | 296 message_loop_for_io()->PostTask(FROM_HERE, |
298 base::Bind(&RawChannelPosix::WaitToWrite, | 297 base::Bind(&RawChannelPosix::WaitToWrite, |
299 weak_ptr_factory_.GetWeakPtr())); | 298 weak_ptr_factory_.GetWeakPtr())); |
300 pending_write_ = true; | 299 pending_write_ = true; |
301 return IO_PENDING; | 300 return IO_PENDING; |
302 } | 301 } |
303 | 302 |
304 if (message_loop_for_io()->WatchFileDescriptor( | 303 if (message_loop_for_io()->WatchFileDescriptor( |
305 fd_.get().fd, | 304 fd_.get().fd, false, base::MessageLoopForIO::WATCH_WRITE, |
306 false, | 305 write_watcher_.get(), this)) { |
307 base::MessageLoopForIO::WATCH_WRITE, | |
308 write_watcher_.get(), | |
309 this)) { | |
310 pending_write_ = true; | 306 pending_write_ = true; |
311 return IO_PENDING; | 307 return IO_PENDING; |
312 } | 308 } |
313 | 309 |
314 return IO_FAILED_UNKNOWN; | 310 return IO_FAILED_UNKNOWN; |
315 } | 311 } |
316 | 312 |
317 bool RawChannelPosix::OnInit() { | 313 bool RawChannelPosix::OnInit() { |
318 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); | 314 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); |
319 | 315 |
320 DCHECK(!read_watcher_); | 316 DCHECK(!read_watcher_); |
321 read_watcher_.reset(new base::MessageLoopForIO::FileDescriptorWatcher()); | 317 read_watcher_.reset(new base::MessageLoopForIO::FileDescriptorWatcher()); |
322 DCHECK(!write_watcher_); | 318 DCHECK(!write_watcher_); |
323 write_watcher_.reset(new base::MessageLoopForIO::FileDescriptorWatcher()); | 319 write_watcher_.reset(new base::MessageLoopForIO::FileDescriptorWatcher()); |
324 | 320 |
325 if (!message_loop_for_io()->WatchFileDescriptor( | 321 if (!message_loop_for_io()->WatchFileDescriptor( |
326 fd_.get().fd, | 322 fd_.get().fd, true, base::MessageLoopForIO::WATCH_READ, |
327 true, | 323 read_watcher_.get(), this)) { |
328 base::MessageLoopForIO::WATCH_READ, | |
329 read_watcher_.get(), | |
330 this)) { | |
331 // TODO(vtl): I'm not sure |WatchFileDescriptor()| actually fails cleanly | 324 // TODO(vtl): I'm not sure |WatchFileDescriptor()| actually fails cleanly |
332 // (in the sense of returning the message loop's state to what it was before | 325 // (in the sense of returning the message loop's state to what it was before |
333 // it was called). | 326 // it was called). |
334 read_watcher_.reset(); | 327 read_watcher_.reset(); |
335 write_watcher_.reset(); | 328 write_watcher_.reset(); |
336 return false; | 329 return false; |
337 } | 330 } |
338 | 331 |
339 return true; | 332 return true; |
340 } | 333 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 if (read_platform_handles_.size() > old_num_platform_handles) { | 407 if (read_platform_handles_.size() > old_num_platform_handles) { |
415 DCHECK_LE(read_platform_handles_.size() - old_num_platform_handles, | 408 DCHECK_LE(read_platform_handles_.size() - old_num_platform_handles, |
416 embedder::kPlatformChannelMaxNumHandles); | 409 embedder::kPlatformChannelMaxNumHandles); |
417 | 410 |
418 // We should never accumulate more than |TransportData::kMaxPlatformHandles | 411 // We should never accumulate more than |TransportData::kMaxPlatformHandles |
419 // + embedder::kPlatformChannelMaxNumHandles| handles. (The latter part is | 412 // + embedder::kPlatformChannelMaxNumHandles| handles. (The latter part is |
420 // possible because we could have accumulated all the handles for a message, | 413 // possible because we could have accumulated all the handles for a message, |
421 // then received the message data plus the first set of handles for the next | 414 // then received the message data plus the first set of handles for the next |
422 // message in the subsequent |recvmsg()|.) | 415 // message in the subsequent |recvmsg()|.) |
423 if (read_platform_handles_.size() > | 416 if (read_platform_handles_.size() > |
424 (TransportData::kMaxPlatformHandles + | 417 (TransportData::GetMaxPlatformHandles() + |
425 embedder::kPlatformChannelMaxNumHandles)) { | 418 embedder::kPlatformChannelMaxNumHandles)) { |
426 LOG(ERROR) << "Received too many platform handles"; | 419 LOG(ERROR) << "Received too many platform handles"; |
427 embedder::CloseAllPlatformHandles(&read_platform_handles_); | 420 embedder::CloseAllPlatformHandles(&read_platform_handles_); |
428 read_platform_handles_.clear(); | 421 read_platform_handles_.clear(); |
429 return IO_FAILED_UNKNOWN; | 422 return IO_FAILED_UNKNOWN; |
430 } | 423 } |
431 } | 424 } |
432 | 425 |
433 if (read_result > 0) { | 426 if (read_result > 0) { |
434 *bytes_read = static_cast<size_t>(read_result); | 427 *bytes_read = static_cast<size_t>(read_result); |
(...skipping 13 matching lines...) Expand all Loading... |
448 PLOG(WARNING) << "recvmsg"; | 441 PLOG(WARNING) << "recvmsg"; |
449 return IO_FAILED_UNKNOWN; | 442 return IO_FAILED_UNKNOWN; |
450 } | 443 } |
451 | 444 |
452 void RawChannelPosix::WaitToWrite() { | 445 void RawChannelPosix::WaitToWrite() { |
453 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); | 446 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); |
454 | 447 |
455 DCHECK(write_watcher_); | 448 DCHECK(write_watcher_); |
456 | 449 |
457 if (!message_loop_for_io()->WatchFileDescriptor( | 450 if (!message_loop_for_io()->WatchFileDescriptor( |
458 fd_.get().fd, | 451 fd_.get().fd, false, base::MessageLoopForIO::WATCH_WRITE, |
459 false, | 452 write_watcher_.get(), this)) { |
460 base::MessageLoopForIO::WATCH_WRITE, | |
461 write_watcher_.get(), | |
462 this)) { | |
463 { | 453 { |
464 base::AutoLock locker(write_lock()); | 454 base::AutoLock locker(write_lock()); |
465 | 455 |
466 DCHECK(pending_write_); | 456 DCHECK(pending_write_); |
467 pending_write_ = false; | 457 pending_write_ = false; |
468 } | 458 } |
469 OnWriteCompleted(IO_FAILED_UNKNOWN, 0, 0); | 459 OnWriteCompleted(IO_FAILED_UNKNOWN, 0, 0); |
470 } | 460 } |
471 } | 461 } |
472 | 462 |
473 } // namespace | 463 } // namespace |
474 | 464 |
475 // ----------------------------------------------------------------------------- | 465 // ----------------------------------------------------------------------------- |
476 | 466 |
477 // Static factory method declared in raw_channel.h. | 467 // Static factory method declared in raw_channel.h. |
478 // static | 468 // static |
479 scoped_ptr<RawChannel> RawChannel::Create( | 469 scoped_ptr<RawChannel> RawChannel::Create( |
480 embedder::ScopedPlatformHandle handle) { | 470 embedder::ScopedPlatformHandle handle) { |
481 return make_scoped_ptr(new RawChannelPosix(handle.Pass())); | 471 return make_scoped_ptr(new RawChannelPosix(handle.Pass())); |
482 } | 472 } |
483 | 473 |
484 } // namespace system | 474 } // namespace system |
485 } // namespace mojo | 475 } // namespace mojo |
OLD | NEW |