| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/ipc_channel_posix.h" | 5 #include "ipc/ipc_channel_posix.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <stddef.h> | 9 #include <stddef.h> |
| 10 #include <sys/types.h> | 10 #include <sys/types.h> |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 // | 72 // |
| 73 // TODO(port): a client process cannot connect to multiple IPC channels with | 73 // TODO(port): a client process cannot connect to multiple IPC channels with |
| 74 // this scheme. | 74 // this scheme. |
| 75 | 75 |
| 76 class PipeMap { | 76 class PipeMap { |
| 77 public: | 77 public: |
| 78 static PipeMap* GetInstance() { | 78 static PipeMap* GetInstance() { |
| 79 return Singleton<PipeMap>::get(); | 79 return Singleton<PipeMap>::get(); |
| 80 } | 80 } |
| 81 | 81 |
| 82 ~PipeMap() { |
| 83 // Shouldn't have left over pipes. |
| 84 DCHECK(map_.size() == 0); |
| 85 } |
| 86 |
| 82 // Lookup a given channel id. Return -1 if not found. | 87 // Lookup a given channel id. Return -1 if not found. |
| 83 int Lookup(const std::string& channel_id) { | 88 int Lookup(const std::string& channel_id) { |
| 84 AutoLock locked(lock_); | 89 AutoLock locked(lock_); |
| 85 | 90 |
| 86 ChannelToFDMap::const_iterator i = map_.find(channel_id); | 91 ChannelToFDMap::const_iterator i = map_.find(channel_id); |
| 87 if (i == map_.end()) | 92 if (i == map_.end()) |
| 88 return -1; | 93 return -1; |
| 89 return i->second; | 94 return i->second; |
| 90 } | 95 } |
| 91 | 96 |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 // the receiver has read enough data to allow passing the FD over atomically. | 272 // the receiver has read enough data to allow passing the FD over atomically. |
| 268 return errno == EAGAIN || errno == EMSGSIZE; | 273 return errno == EAGAIN || errno == EMSGSIZE; |
| 269 #else | 274 #else |
| 270 return errno == EAGAIN; | 275 return errno == EAGAIN; |
| 271 #endif | 276 #endif |
| 272 } | 277 } |
| 273 | 278 |
| 274 } // namespace | 279 } // namespace |
| 275 //------------------------------------------------------------------------------ | 280 //------------------------------------------------------------------------------ |
| 276 | 281 |
| 277 Channel::ChannelImpl::ChannelImpl(const std::string& channel_id, Mode mode, | 282 Channel::ChannelImpl::ChannelImpl(const IPC::ChannelHandle& channel_handle, |
| 278 Listener* listener) | 283 Mode mode, Listener* listener) |
| 279 : mode_(mode), | 284 : mode_(mode), |
| 280 is_blocked_on_write_(false), | 285 is_blocked_on_write_(false), |
| 281 message_send_bytes_written_(0), | 286 message_send_bytes_written_(0), |
| 282 uses_fifo_( | 287 uses_fifo_( |
| 283 CommandLine::ForCurrentProcess()->HasSwitch(switches::kIPCUseFIFO) || | 288 CommandLine::ForCurrentProcess()->HasSwitch(switches::kIPCUseFIFO) || |
| 284 mode == MODE_NAMED_SERVER || mode == MODE_NAMED_CLIENT), | 289 mode == MODE_NAMED_SERVER || mode == MODE_NAMED_CLIENT), |
| 285 server_listen_pipe_(-1), | 290 server_listen_pipe_(-1), |
| 286 pipe_(-1), | 291 pipe_(-1), |
| 287 client_pipe_(-1), | 292 client_pipe_(-1), |
| 288 #if !defined(OS_MACOSX) | 293 #if !defined(OS_MACOSX) |
| 289 fd_pipe_(-1), | 294 fd_pipe_(-1), |
| 290 remote_fd_pipe_(-1), | 295 remote_fd_pipe_(-1), |
| 291 #endif | 296 #endif |
| 292 listener_(listener), | 297 listener_(listener), |
| 293 waiting_connect_(true), | 298 waiting_connect_(true), |
| 294 factory_(this) { | 299 factory_(this) { |
| 295 if (mode_ == MODE_NAMED_SERVER) | 300 if (mode_ == MODE_NAMED_SERVER) |
| 296 mode_ = MODE_SERVER; | 301 mode_ = MODE_SERVER; |
| 297 if (mode_ == MODE_NAMED_CLIENT) | 302 if (mode_ == MODE_NAMED_CLIENT) |
| 298 mode_ = MODE_CLIENT; | 303 mode_ = MODE_CLIENT; |
| 299 | 304 |
| 300 if (!CreatePipe(channel_id, mode_)) { | 305 if (!CreatePipe(channel_handle, mode_)) { |
| 301 // The pipe may have been closed already. | 306 // The pipe may have been closed already. |
| 302 PLOG(WARNING) << "Unable to create pipe named \"" << channel_id | 307 LOG(WARNING) << "Unable to create pipe named \"" << channel_handle.name |
| 303 << "\" in " << (mode_ == MODE_SERVER ? "server" : "client") | 308 << "\" in " << (mode_ == MODE_SERVER ? "server" : "client") |
| 304 << " mode"; | 309 << " mode"; |
| 305 } | 310 } |
| 306 } | 311 } |
| 307 | 312 |
| 308 Channel::ChannelImpl::~ChannelImpl() { | 313 Channel::ChannelImpl::~ChannelImpl() { |
| 309 Close(); | 314 Close(); |
| 310 } | 315 } |
| 311 | 316 |
| 312 // static | 317 // static |
| (...skipping 29 matching lines...) Expand all Loading... |
| 342 PLOG(ERROR) << "close"; | 347 PLOG(ERROR) << "close"; |
| 343 return false; | 348 return false; |
| 344 } | 349 } |
| 345 | 350 |
| 346 *fd1 = pipe_fds[0]; | 351 *fd1 = pipe_fds[0]; |
| 347 *fd2 = pipe_fds[1]; | 352 *fd2 = pipe_fds[1]; |
| 348 | 353 |
| 349 return true; | 354 return true; |
| 350 } | 355 } |
| 351 | 356 |
| 352 bool Channel::ChannelImpl::CreatePipe(const std::string& channel_id, | 357 bool Channel::ChannelImpl::CreatePipe(const IPC::ChannelHandle &channel_handle, |
| 353 Mode mode) { | 358 Mode mode) { |
| 354 DCHECK(server_listen_pipe_ == -1 && pipe_ == -1); | 359 DCHECK(server_listen_pipe_ == -1 && pipe_ == -1); |
| 355 | 360 pipe_name_ = channel_handle.name; |
| 361 pipe_ = channel_handle.socket.fd; |
| 356 if (uses_fifo_) { | 362 if (uses_fifo_) { |
| 357 // This only happens in unit tests; see the comment above PipeMap. | 363 // This only happens in unit tests; see the comment above PipeMap. |
| 358 // TODO(playmobil): We shouldn't need to create fifos on disk. | 364 // TODO(playmobil): We shouldn't need to create fifos on disk. |
| 359 // TODO(playmobil): If we do, they should be in the user data directory. | 365 // TODO(playmobil): If we do, they should be in the user data directory. |
| 360 // TODO(playmobil): Cleanup any stale fifos. | 366 // TODO(playmobil): Cleanup any stale fifos. |
| 361 pipe_name_ = channel_id; | |
| 362 if (mode == MODE_SERVER) { | 367 if (mode == MODE_SERVER) { |
| 363 if (!CreateServerFifo(pipe_name_, &server_listen_pipe_)) { | 368 if (!CreateServerFifo(pipe_name_, &server_listen_pipe_)) { |
| 364 return false; | 369 return false; |
| 365 } | 370 } |
| 366 } else { | 371 } else { |
| 367 if (!ClientConnectToFifo(pipe_name_, &pipe_)) { | 372 if (!ClientConnectToFifo(pipe_name_, &pipe_)) { |
| 368 return false; | 373 return false; |
| 369 } | 374 } |
| 370 waiting_connect_ = false; | 375 waiting_connect_ = false; |
| 371 } | 376 } |
| 372 } else { | 377 } else { |
| 373 // This is the normal (non-unit-test) case, where we're using sockets. | 378 // This is the normal (non-unit-test) case, where we're using sockets. |
| 374 // Three possible cases: | 379 // Three possible cases: |
| 375 // 1) It's for a channel we already have a pipe for; reuse it. | 380 // 1) It's for a channel we already have a pipe for; reuse it. |
| 376 // 2) It's the initial IPC channel: | 381 // 2) It's the initial IPC channel: |
| 377 // 2a) Server side: create the pipe. | 382 // 2a) Server side: create the pipe. |
| 378 // 2b) Client side: Pull the pipe out of the GlobalDescriptors set. | 383 // 2b) Client side: Pull the pipe out of the GlobalDescriptors set. |
| 379 pipe_name_ = channel_id; | 384 if (pipe_ < 0) { |
| 380 pipe_ = ChannelNameToFD(pipe_name_); | 385 pipe_ = ChannelNameToFD(pipe_name_); |
| 386 } |
| 381 if (pipe_ < 0) { | 387 if (pipe_ < 0) { |
| 382 // Initial IPC channel. | 388 // Initial IPC channel. |
| 383 if (mode == MODE_SERVER) { | 389 if (mode == MODE_SERVER) { |
| 384 if (!SocketPair(&pipe_, &client_pipe_)) | 390 if (!SocketPair(&pipe_, &client_pipe_)) |
| 385 return false; | 391 return false; |
| 386 AddChannelSocket(pipe_name_, client_pipe_); | 392 AddChannelSocket(pipe_name_, client_pipe_); |
| 387 } else { | 393 } else { |
| 388 // Guard against inappropriate reuse of the initial IPC channel. If | 394 // Guard against inappropriate reuse of the initial IPC channel. If |
| 389 // an IPC channel closes and someone attempts to reuse it by name, the | 395 // an IPC channel closes and someone attempts to reuse it by name, the |
| 390 // initial channel must not be recycled here. http://crbug.com/26754. | 396 // initial channel must not be recycled here. http://crbug.com/26754. |
| (...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1058 for (std::vector<int>::iterator | 1064 for (std::vector<int>::iterator |
| 1059 i = input_overflow_fds_.begin(); i != input_overflow_fds_.end(); ++i) { | 1065 i = input_overflow_fds_.begin(); i != input_overflow_fds_.end(); ++i) { |
| 1060 if (HANDLE_EINTR(close(*i)) < 0) | 1066 if (HANDLE_EINTR(close(*i)) < 0) |
| 1061 PLOG(ERROR) << "close"; | 1067 PLOG(ERROR) << "close"; |
| 1062 } | 1068 } |
| 1063 input_overflow_fds_.clear(); | 1069 input_overflow_fds_.clear(); |
| 1064 } | 1070 } |
| 1065 | 1071 |
| 1066 //------------------------------------------------------------------------------ | 1072 //------------------------------------------------------------------------------ |
| 1067 // Channel's methods simply call through to ChannelImpl. | 1073 // Channel's methods simply call through to ChannelImpl. |
| 1068 Channel::Channel(const std::string& channel_id, Mode mode, | 1074 Channel::Channel(const IPC::ChannelHandle& channel_handle, Mode mode, |
| 1069 Listener* listener) | 1075 Listener* listener) |
| 1070 : channel_impl_(new ChannelImpl(channel_id, mode, listener)) { | 1076 : channel_impl_(new ChannelImpl(channel_handle, mode, listener)) { |
| 1071 } | 1077 } |
| 1072 | 1078 |
| 1073 Channel::~Channel() { | 1079 Channel::~Channel() { |
| 1074 delete channel_impl_; | 1080 delete channel_impl_; |
| 1075 } | 1081 } |
| 1076 | 1082 |
| 1077 bool Channel::Connect() { | 1083 bool Channel::Connect() { |
| 1078 return channel_impl_->Connect(); | 1084 return channel_impl_->Connect(); |
| 1079 } | 1085 } |
| 1080 | 1086 |
| 1081 void Channel::Close() { | 1087 void Channel::Close() { |
| 1082 channel_impl_->Close(); | 1088 channel_impl_->Close(); |
| 1083 } | 1089 } |
| 1084 | 1090 |
| 1085 void Channel::set_listener(Listener* listener) { | 1091 void Channel::set_listener(Listener* listener) { |
| 1086 channel_impl_->set_listener(listener); | 1092 channel_impl_->set_listener(listener); |
| 1087 } | 1093 } |
| 1088 | 1094 |
| 1089 bool Channel::Send(Message* message) { | 1095 bool Channel::Send(Message* message) { |
| 1090 return channel_impl_->Send(message); | 1096 return channel_impl_->Send(message); |
| 1091 } | 1097 } |
| 1092 | 1098 |
| 1093 int Channel::GetClientFileDescriptor() const { | 1099 int Channel::GetClientFileDescriptor() const { |
| 1094 return channel_impl_->GetClientFileDescriptor(); | 1100 return channel_impl_->GetClientFileDescriptor(); |
| 1095 } | 1101 } |
| 1096 | 1102 |
| 1097 } // namespace IPC | 1103 } // namespace IPC |
| OLD | NEW |