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 |