Chromium Code Reviews| 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 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 366 | 366 |
| 367 // Four possible cases: | 367 // Four possible cases: |
| 368 // 1) It's a channel wrapping a pipe that is given to us. | 368 // 1) It's a channel wrapping a pipe that is given to us. |
| 369 // 2) It's for a named channel, so we create it. | 369 // 2) It's for a named channel, so we create it. |
| 370 // 3) It's for a client that we implement ourself. This is used | 370 // 3) It's for a client that we implement ourself. This is used |
| 371 // in unittesting. | 371 // in unittesting. |
| 372 // 4) It's the initial IPC channel: | 372 // 4) It's the initial IPC channel: |
| 373 // 4a) Client side: Pull the pipe out of the GlobalDescriptors set. | 373 // 4a) Client side: Pull the pipe out of the GlobalDescriptors set. |
| 374 // 4b) Server side: create the pipe. | 374 // 4b) Server side: create the pipe. |
| 375 | 375 |
| 376 int local_pipe = -1; | |
| 376 if (channel_handle.socket.fd != -1) { | 377 if (channel_handle.socket.fd != -1) { |
| 377 // Case 1 from comment above. | 378 // Case 1 from comment above. |
| 378 pipe_ = channel_handle.socket.fd; | 379 local_pipe = channel_handle.socket.fd; |
| 379 #if defined(IPC_USES_READWRITE) | 380 #if defined(IPC_USES_READWRITE) |
| 380 // Test the socket passed into us to make sure it is nonblocking. | 381 // Test the socket passed into us to make sure it is nonblocking. |
| 381 // We don't want to call read/write on a blocking socket. | 382 // We don't want to call read/write on a blocking socket. |
| 382 int value = fcntl(pipe_, F_GETFL); | 383 int value = fcntl(local_pipe, F_GETFL); |
| 383 if (value == -1) { | 384 if (value == -1) { |
| 384 PLOG(ERROR) << "fcntl(F_GETFL) " << pipe_name_; | 385 PLOG(ERROR) << "fcntl(F_GETFL) " << pipe_name_; |
| 385 return false; | 386 return false; |
| 386 } | 387 } |
| 387 if (!(value & O_NONBLOCK)) { | 388 if (!(value & O_NONBLOCK)) { |
| 388 LOG(ERROR) << "Socket " << pipe_name_ << " must be O_NONBLOCK"; | 389 LOG(ERROR) << "Socket " << pipe_name_ << " must be O_NONBLOCK"; |
| 389 return false; | 390 return false; |
| 390 } | 391 } |
| 391 #endif // IPC_USES_READWRITE | 392 #endif // IPC_USES_READWRITE |
| 392 } else if (mode_ & MODE_NAMED_FLAG) { | 393 } else if (mode_ & MODE_NAMED_FLAG) { |
| 393 // Case 2 from comment above. | 394 // Case 2 from comment above. |
| 394 if (mode_ & MODE_SERVER_FLAG) { | 395 if (mode_ & MODE_SERVER_FLAG) { |
| 395 if (!CreateServerUnixDomainSocket(pipe_name_, &pipe_)) { | 396 if (!CreateServerUnixDomainSocket(pipe_name_, &local_pipe)) { |
| 396 return false; | 397 return false; |
| 397 } | 398 } |
| 398 must_unlink_ = true; | 399 must_unlink_ = true; |
| 399 } else if (mode_ & MODE_CLIENT_FLAG) { | 400 } else if (mode_ & MODE_CLIENT_FLAG) { |
| 400 if (!CreateClientUnixDomainSocket(pipe_name_, &pipe_)) { | 401 if (!CreateClientUnixDomainSocket(pipe_name_, &local_pipe)) { |
| 401 return false; | 402 return false; |
| 402 } | 403 } |
| 403 } else { | 404 } else { |
| 404 NOTREACHED(); | 405 LOG(ERROR) << "Bad mode: " << mode_; |
|
jeremy
2011/03/02 19:05:45
Why did you changed the NOTREACHED()'s to LOG(ERRO
| |
| 405 return false; | 406 return false; |
| 406 } | 407 } |
| 407 } else { | 408 } else { |
| 408 pipe_ = PipeMap::GetInstance()->Lookup(pipe_name_); | 409 local_pipe = PipeMap::GetInstance()->Lookup(pipe_name_); |
| 409 if (mode_ & MODE_CLIENT_FLAG) { | 410 if (mode_ & MODE_CLIENT_FLAG) { |
| 410 if (pipe_ != -1) { | 411 if (local_pipe != -1) { |
| 411 // Case 3 from comment above. | 412 // Case 3 from comment above. |
| 412 // We only allow one connection. | 413 // We only allow one connection. |
| 413 pipe_ = HANDLE_EINTR(dup(pipe_)); | 414 local_pipe = HANDLE_EINTR(dup(local_pipe)); |
| 414 PipeMap::GetInstance()->RemoveAndClose(pipe_name_); | 415 PipeMap::GetInstance()->RemoveAndClose(pipe_name_); |
| 415 } else { | 416 } else { |
| 416 // Case 4a from comment above. | 417 // Case 4a from comment above. |
| 417 // Guard against inappropriate reuse of the initial IPC channel. If | 418 // Guard against inappropriate reuse of the initial IPC channel. If |
| 418 // an IPC channel closes and someone attempts to reuse it by name, the | 419 // an IPC channel closes and someone attempts to reuse it by name, the |
| 419 // initial channel must not be recycled here. http://crbug.com/26754. | 420 // initial channel must not be recycled here. http://crbug.com/26754. |
| 420 static bool used_initial_channel = false; | 421 static bool used_initial_channel = false; |
| 421 if (used_initial_channel) { | 422 if (used_initial_channel) { |
| 422 LOG(FATAL) << "Denying attempt to reuse initial IPC channel for " | 423 LOG(FATAL) << "Denying attempt to reuse initial IPC channel for " |
| 423 << pipe_name_; | 424 << pipe_name_; |
| 424 return false; | 425 return false; |
| 425 } | 426 } |
| 426 used_initial_channel = true; | 427 used_initial_channel = true; |
| 427 | 428 |
| 428 pipe_ = base::GlobalDescriptors::GetInstance()->Get(kPrimaryIPCChannel); | 429 local_pipe = |
| 430 base::GlobalDescriptors::GetInstance()->Get(kPrimaryIPCChannel); | |
| 429 } | 431 } |
| 430 } else if (mode_ & MODE_SERVER_FLAG) { | 432 } else if (mode_ & MODE_SERVER_FLAG) { |
| 431 // Case 4b from comment above. | 433 // Case 4b from comment above. |
| 432 if (pipe_ != -1) { | 434 if (local_pipe != -1) { |
| 433 LOG(ERROR) << "Server already exists for " << pipe_name_; | 435 LOG(ERROR) << "Server already exists for " << pipe_name_; |
| 434 return false; | 436 return false; |
| 435 } | 437 } |
| 436 if (!SocketPair(&pipe_, &client_pipe_)) | 438 if (!SocketPair(&local_pipe, &client_pipe_)) |
| 437 return false; | 439 return false; |
| 438 PipeMap::GetInstance()->Insert(pipe_name_, client_pipe_); | 440 PipeMap::GetInstance()->Insert(pipe_name_, client_pipe_); |
| 439 } else { | 441 } else { |
| 440 NOTREACHED(); | 442 LOG(ERROR) << "Bad mode: " << mode_; |
| 441 return false; | 443 return false; |
| 442 } | 444 } |
| 443 } | 445 } |
| 444 | 446 |
| 445 if ((mode_ & MODE_SERVER_FLAG) && (mode_ & MODE_NAMED_FLAG)) { | |
| 446 server_listen_pipe_ = pipe_; | |
| 447 pipe_ = -1; | |
| 448 } | |
| 449 | |
| 450 #if defined(IPC_USES_READWRITE) | 447 #if defined(IPC_USES_READWRITE) |
| 451 // Create a dedicated socketpair() for exchanging file descriptors. | 448 // Create a dedicated socketpair() for exchanging file descriptors. |
| 452 // See comments for IPC_USES_READWRITE for details. | 449 // See comments for IPC_USES_READWRITE for details. |
| 453 if (mode_ & MODE_CLIENT_FLAG) { | 450 if (mode_ & MODE_CLIENT_FLAG) { |
| 454 if (!SocketPair(&fd_pipe_, &remote_fd_pipe_)) { | 451 if (!SocketPair(&fd_pipe_, &remote_fd_pipe_)) { |
| 455 return false; | 452 return false; |
| 456 } | 453 } |
| 457 } | 454 } |
| 458 #endif // IPC_USES_READWRITE | 455 #endif // IPC_USES_READWRITE |
| 459 | 456 |
| 457 if ((mode_ & MODE_SERVER_FLAG) && (mode_ & MODE_NAMED_FLAG)) { | |
| 458 server_listen_pipe_ = local_pipe; | |
| 459 local_pipe = -1; | |
| 460 } | |
| 461 | |
| 462 pipe_ = local_pipe; | |
| 460 return true; | 463 return true; |
| 461 } | 464 } |
| 462 | 465 |
| 463 bool Channel::ChannelImpl::Connect() { | 466 bool Channel::ChannelImpl::Connect() { |
| 464 if (server_listen_pipe_ == -1 && pipe_ == -1) { | 467 if (server_listen_pipe_ == -1 && pipe_ == -1) { |
| 465 DLOG(INFO) << "Must call create on a channel before calling connect"; | 468 DLOG(INFO) << "Channel creation failed: " << pipe_name_; |
| 466 return false; | 469 return false; |
| 467 } | 470 } |
| 468 | 471 |
| 469 bool did_connect = true; | 472 bool did_connect = true; |
| 470 if (server_listen_pipe_ != -1) { | 473 if (server_listen_pipe_ != -1) { |
| 471 // Watch the pipe for connections, and turn any connections into | 474 // Watch the pipe for connections, and turn any connections into |
| 472 // active sockets. | 475 // active sockets. |
| 473 MessageLoopForIO::current()->WatchFileDescriptor( | 476 MessageLoopForIO::current()->WatchFileDescriptor( |
| 474 server_listen_pipe_, | 477 server_listen_pipe_, |
| 475 true, | 478 true, |
| (...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1156 | 1159 |
| 1157 bool Channel::HasAcceptedConnection() const { | 1160 bool Channel::HasAcceptedConnection() const { |
| 1158 return channel_impl_->HasAcceptedConnection(); | 1161 return channel_impl_->HasAcceptedConnection(); |
| 1159 } | 1162 } |
| 1160 | 1163 |
| 1161 void Channel::ResetToAcceptingConnectionState() { | 1164 void Channel::ResetToAcceptingConnectionState() { |
| 1162 channel_impl_->ResetToAcceptingConnectionState(); | 1165 channel_impl_->ResetToAcceptingConnectionState(); |
| 1163 } | 1166 } |
| 1164 | 1167 |
| 1165 } // namespace IPC | 1168 } // namespace IPC |
| OLD | NEW |