|
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 #include <list> |
|
16 |
|
17 #include "base/message_loop.h" |
|
18 #include "chrome/common/file_descriptor_set_posix.h" |
|
19 |
|
20 namespace IPC { |
|
21 |
|
22 // An implementation of ChannelImpl for POSIX systems that works via |
|
23 // socketpairs. See the .cc file for an overview of the implementation. |
|
24 class Channel::ChannelImpl : public MessageLoopForIO::Watcher { |
|
25 public: |
|
26 // Mirror methods of Channel, see ipc_channel.h for description. |
|
27 ChannelImpl(const std::wstring& channel_id, Mode mode, Listener* listener); |
|
28 ChannelImpl(int fd, Mode mode, Listener* listener); |
|
29 ~ChannelImpl() { Close(); } |
|
30 bool Connect(); |
|
31 void Close(); |
|
32 Listener* set_listener(Listener* listener) { |
|
33 Listener* old = listener_; |
|
34 listener_ = listener; |
|
35 return old; |
|
36 } |
|
37 bool Send(Message* message); |
|
38 void GetClientFileDescriptorMapping(int *src_fd, int *dest_fd) const; |
|
39 |
|
40 void ResetFileDescriptor(int fd); |
|
41 |
|
42 int GetFileDescriptor() const { |
|
43 return pipe_; |
|
44 } |
|
45 void CloseClientFileDescriptor(); |
|
46 |
|
47 // See the comment in ipc_channel.h for info on Unsound_IsClosed() and |
|
48 // Unsound_NumQueuedMessages(). |
|
49 bool Unsound_IsClosed() const; |
|
50 uint32_t Unsound_NumQueuedMessages() const; |
|
51 |
|
52 private: |
|
53 void Init(Mode mode, Listener* listener); |
|
54 bool CreatePipe(const std::wstring& channel_id, Mode mode); |
|
55 bool EnqueueHelloMessage(); |
|
56 |
|
57 bool ProcessIncomingMessages(); |
|
58 bool ProcessOutgoingMessages(); |
|
59 |
|
60 // MessageLoopForIO::Watcher implementation. |
|
61 virtual void OnFileCanReadWithoutBlocking(int fd); |
|
62 virtual void OnFileCanWriteWithoutBlocking(int fd); |
|
63 |
|
64 #if defined(OS_MACOSX) |
|
65 void CloseDescriptors(uint32_t pending_fd_id); |
|
66 #endif |
|
67 |
|
68 void OutputQueuePush(Message* msg); |
|
69 void OutputQueuePop(); |
|
70 |
|
71 Mode mode_; |
|
72 |
|
73 // After accepting one client connection on our server socket we want to |
|
74 // stop listening. |
|
75 MessageLoopForIO::FileDescriptorWatcher server_listen_connection_watcher_; |
|
76 MessageLoopForIO::FileDescriptorWatcher read_watcher_; |
|
77 MessageLoopForIO::FileDescriptorWatcher write_watcher_; |
|
78 |
|
79 // Indicates whether we're currently blocked waiting for a write to complete. |
|
80 bool is_blocked_on_write_; |
|
81 |
|
82 // If sending a message blocks then we use this variable |
|
83 // to keep track of where we are. |
|
84 size_t message_send_bytes_written_; |
|
85 |
|
86 // If the kTestingChannelID flag is specified, we use a FIFO instead of |
|
87 // a socketpair(). |
|
88 bool uses_fifo_; |
|
89 |
|
90 int server_listen_pipe_; |
|
91 int pipe_; |
|
92 int client_pipe_; // The client end of our socketpair(). |
|
93 |
|
94 // The "name" of our pipe. On Windows this is the global identifier for |
|
95 // the pipe. On POSIX it's used as a key in a local map of file descriptors. |
|
96 std::string pipe_name_; |
|
97 |
|
98 Listener* listener_; |
|
99 |
|
100 // Messages to be sent are queued here. |
|
101 std::queue<Message*> output_queue_; |
|
102 |
|
103 // We read from the pipe into this buffer |
|
104 char input_buf_[Channel::kReadBufferSize]; |
|
105 |
|
106 enum { |
|
107 // We assume a worst case: kReadBufferSize bytes of messages, where each |
|
108 // message has no payload and a full complement of descriptors. |
|
109 MAX_READ_FDS = (Channel::kReadBufferSize / sizeof(IPC::Message::Header)) * |
|
110 FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE |
|
111 }; |
|
112 |
|
113 // This is a control message buffer large enough to hold kMaxReadFDs |
|
114 #if defined(OS_MACOSX) || defined(OS_NETBSD) |
|
115 // TODO(agl): OSX appears to have non-constant CMSG macros! |
|
116 char input_cmsg_buf_[1024]; |
|
117 #else |
|
118 char input_cmsg_buf_[CMSG_SPACE(sizeof(int) * MAX_READ_FDS)]; |
|
119 #endif |
|
120 |
|
121 // Large messages that span multiple pipe buffers, get built-up using |
|
122 // this buffer. |
|
123 std::string input_overflow_buf_; |
|
124 std::vector<int> input_overflow_fds_; |
|
125 |
|
126 // In server-mode, we have to wait for the client to connect before we |
|
127 // can begin reading. We make use of the input_state_ when performing |
|
128 // the connect operation in overlapped mode. |
|
129 bool waiting_connect_; |
|
130 |
|
131 // This flag is set when processing incoming messages. It is used to |
|
132 // avoid recursing through ProcessIncomingMessages, which could cause |
|
133 // problems. TODO(darin): make this unnecessary |
|
134 bool processing_incoming_; |
|
135 |
|
136 // This flag is set after we've closed the channel. |
|
137 bool closed_; |
|
138 |
|
139 #if defined(OS_MACOSX) |
|
140 struct PendingDescriptors { |
|
141 uint32_t id; |
|
142 scoped_refptr<FileDescriptorSet> fds; |
|
143 |
|
144 PendingDescriptors() : id(0) { } |
|
145 PendingDescriptors(uint32_t id, FileDescriptorSet *fds) |
|
146 : id(id), |
|
147 fds(fds) |
|
148 { } |
|
149 }; |
|
150 |
|
151 std::list<PendingDescriptors> pending_fds_; |
|
152 |
|
153 // A generation ID for RECEIVED_FD messages. |
|
154 uint32_t last_pending_fd_id_; |
|
155 #endif |
|
156 |
|
157 // This variable is updated so it matches output_queue_.size(), except we can |
|
158 // read output_queue_length_ from any thread (if we're OK getting an |
|
159 // occasional out-of-date or bogus value). We use output_queue_length_ to |
|
160 // implement Unsound_NumQueuedMessages. |
|
161 size_t output_queue_length_; |
|
162 |
|
163 ScopedRunnableMethodFactory<ChannelImpl> factory_; |
|
164 |
|
165 DISALLOW_COPY_AND_ASSIGN(ChannelImpl); |
|
166 }; |
|
167 |
|
168 } // namespace IPC |
|
169 |
|
170 #endif // CHROME_COMMON_IPC_CHANNEL_POSIX_H_ |