1 : // Copyright (c) 2008 The Chromium Authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifndef CHROME_COMMON_IPC_CHANNEL_POSIX_H_
6 : #define CHROME_COMMON_IPC_CHANNEL_POSIX_H_
7 :
8 : #include "chrome/common/ipc_channel.h"
9 :
10 : #include <sys/socket.h> // for CMSG macros
11 :
12 : #include <queue>
13 : #include <string>
14 : #include <vector>
15 :
16 : #include "base/message_loop.h"
17 : #include "chrome/common/file_descriptor_set_posix.h"
18 :
19 : namespace IPC {
20 :
21 : // An implementation of ChannelImpl for POSIX systems that works via
22 : // socketpairs. See the .cc file for an overview of the implementation.
23 : class Channel::ChannelImpl : public MessageLoopForIO::Watcher {
24 : public:
25 : // Mirror methods of Channel, see ipc_channel.h for description.
26 : ChannelImpl(const std::wstring& channel_id, Mode mode, Listener* listener);
27 : ChannelImpl(int fd, Mode mode, Listener* listener);
28 0 : ~ChannelImpl() { Close(); }
29 : bool Connect();
30 : void Close();
31 0 : Listener* set_listener(Listener* listener) {
32 0 : Listener* old = listener_;
33 0 : listener_ = listener;
34 0 : return old;
35 : }
36 : bool Send(Message* message);
37 : void GetClientFileDescriptorMapping(int *src_fd, int *dest_fd) const;
38 0 : int GetServerFileDescriptor() const {
39 0 : DCHECK(mode_ == MODE_SERVER);
40 0 : return pipe_;
41 : }
42 :
43 : private:
44 : void Init(Mode mode, Listener* listener);
45 : bool CreatePipe(const std::wstring& channel_id, Mode mode);
46 : bool EnqueueHelloMessage();
47 :
48 : bool ProcessIncomingMessages();
49 : bool ProcessOutgoingMessages();
50 :
51 : // MessageLoopForIO::Watcher implementation.
52 : virtual void OnFileCanReadWithoutBlocking(int fd);
53 : virtual void OnFileCanWriteWithoutBlocking(int fd);
54 :
55 : Mode mode_;
56 :
57 : // After accepting one client connection on our server socket we want to
58 : // stop listening.
59 : MessageLoopForIO::FileDescriptorWatcher server_listen_connection_watcher_;
60 : MessageLoopForIO::FileDescriptorWatcher read_watcher_;
61 : MessageLoopForIO::FileDescriptorWatcher write_watcher_;
62 :
63 : // Indicates whether we're currently blocked waiting for a write to complete.
64 : bool is_blocked_on_write_;
65 :
66 : // If sending a message blocks then we use this variable
67 : // to keep track of where we are.
68 : size_t message_send_bytes_written_;
69 :
70 : // If the kTestingChannelID flag is specified, we use a FIFO instead of
71 : // a socketpair().
72 : bool uses_fifo_;
73 :
74 : int server_listen_pipe_;
75 : int pipe_;
76 : int client_pipe_; // The client end of our socketpair().
77 :
78 : // The "name" of our pipe. On Windows this is the global identifier for
79 : // the pipe. On POSIX it's used as a key in a local map of file descriptors.
80 : std::string pipe_name_;
81 :
82 : Listener* listener_;
83 :
84 : // Messages to be sent are queued here.
85 : std::queue<Message*> output_queue_;
86 :
87 : // We read from the pipe into this buffer
88 : char input_buf_[Channel::kReadBufferSize];
89 :
90 : enum {
91 : // We assume a worst case: kReadBufferSize bytes of messages, where each
92 : // message has no payload and a full complement of descriptors.
93 : MAX_READ_FDS = (Channel::kReadBufferSize / sizeof(IPC::Message::Header)) *
94 : FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE,
95 : };
96 :
97 : // This is a control message buffer large enough to hold kMaxReadFDs
98 : #if defined(OS_MACOSX)
99 : // TODO(agl): OSX appears to have non-constant CMSG macros!
100 : char input_cmsg_buf_[1024];
101 : #else
102 : char input_cmsg_buf_[CMSG_SPACE(sizeof(int) * MAX_READ_FDS)];
103 : #endif
104 :
105 : // Large messages that span multiple pipe buffers, get built-up using
106 : // this buffer.
107 : std::string input_overflow_buf_;
108 : std::vector<int> input_overflow_fds_;
109 :
110 : // In server-mode, we have to wait for the client to connect before we
111 : // can begin reading. We make use of the input_state_ when performing
112 : // the connect operation in overlapped mode.
113 : bool waiting_connect_;
114 :
115 : // This flag is set when processing incoming messages. It is used to
116 : // avoid recursing through ProcessIncomingMessages, which could cause
117 : // problems. TODO(darin): make this unnecessary
118 : bool processing_incoming_;
119 :
120 : ScopedRunnableMethodFactory<ChannelImpl> factory_;
121 :
122 : DISALLOW_COPY_AND_ASSIGN(ChannelImpl);
123 : };
124 :
125 : } // namespace IPC
126 :
127 : #endif // CHROME_COMMON_IPC_CHANNEL_POSIX_H_
|