Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : // Copyright (c) 2008 The Chromium Authors. All rights reserved.
4 : // Use of this source code is governed by a BSD-style license that can be
5 : // found in the LICENSE file.
6 :
7 : #ifndef CHROME_COMMON_IPC_CHANNEL_POSIX_H_
8 : #define CHROME_COMMON_IPC_CHANNEL_POSIX_H_
9 :
10 : #include "chrome/common/ipc_channel.h"
11 :
12 : #include <sys/socket.h> // for CMSG macros
13 :
14 : #include <queue>
15 : #include <string>
16 : #include <vector>
17 : #include <list>
18 :
19 : #include "base/message_loop.h"
20 : #include "base/task.h"
21 : #include "chrome/common/file_descriptor_set_posix.h"
22 :
23 : #include "nsAutoPtr.h"
24 :
25 : #include "mozilla/Maybe.h"
26 :
27 : namespace IPC {
28 :
29 : // An implementation of ChannelImpl for POSIX systems that works via
30 : // socketpairs. See the .cc file for an overview of the implementation.
31 : class Channel::ChannelImpl : public MessageLoopForIO::Watcher {
32 : public:
33 : // Mirror methods of Channel, see ipc_channel.h for description.
34 : ChannelImpl(const std::wstring& channel_id, Mode mode, Listener* listener);
35 : ChannelImpl(int fd, Mode mode, Listener* listener);
36 39 : ~ChannelImpl() { Close(); }
37 : bool Connect();
38 : void Close();
39 28 : Listener* set_listener(Listener* listener) {
40 28 : Listener* old = listener_;
41 28 : listener_ = listener;
42 28 : return old;
43 : }
44 : bool Send(Message* message);
45 : void GetClientFileDescriptorMapping(int *src_fd, int *dest_fd) const;
46 :
47 : void ResetFileDescriptor(int fd);
48 :
49 13 : int GetFileDescriptor() const {
50 13 : return pipe_;
51 : }
52 : void CloseClientFileDescriptor();
53 :
54 : // See the comment in ipc_channel.h for info on Unsound_IsClosed() and
55 : // Unsound_NumQueuedMessages().
56 : bool Unsound_IsClosed() const;
57 : uint32_t Unsound_NumQueuedMessages() const;
58 :
59 : private:
60 : void Init(Mode mode, Listener* listener);
61 : bool CreatePipe(const std::wstring& channel_id, Mode mode);
62 : bool EnqueueHelloMessage();
63 :
64 : bool ProcessIncomingMessages();
65 : bool ProcessOutgoingMessages();
66 :
67 : // MessageLoopForIO::Watcher implementation.
68 : virtual void OnFileCanReadWithoutBlocking(int fd);
69 : virtual void OnFileCanWriteWithoutBlocking(int fd);
70 :
71 : #if defined(OS_MACOSX)
72 : void CloseDescriptors(uint32_t pending_fd_id);
73 : #endif
74 :
75 : void OutputQueuePush(Message* msg);
76 : void OutputQueuePop();
77 :
78 : Mode mode_;
79 :
80 : // After accepting one client connection on our server socket we want to
81 : // stop listening.
82 : MessageLoopForIO::FileDescriptorWatcher server_listen_connection_watcher_;
83 : MessageLoopForIO::FileDescriptorWatcher read_watcher_;
84 : MessageLoopForIO::FileDescriptorWatcher write_watcher_;
85 :
86 : // Indicates whether we're currently blocked waiting for a write to complete.
87 : bool is_blocked_on_write_;
88 :
89 : // If sending a message blocks then we use this iterator to keep track of
90 : // where in the message we are. It gets reset when the message is finished
91 : // sending.
92 : mozilla::Maybe<Pickle::BufferList::IterImpl> partial_write_iter_;
93 :
94 : int server_listen_pipe_;
95 : int pipe_;
96 : int client_pipe_; // The client end of our socketpair().
97 :
98 : // The "name" of our pipe. On Windows this is the global identifier for
99 : // the pipe. On POSIX it's used as a key in a local map of file descriptors.
100 : std::string pipe_name_;
101 :
102 : Listener* listener_;
103 :
104 : // Messages to be sent are queued here.
105 : std::queue<Message*> output_queue_;
106 :
107 : // We read from the pipe into this buffer
108 : char input_buf_[Channel::kReadBufferSize];
109 : size_t input_buf_offset_;
110 :
111 : // We want input_cmsg_buf_ to be big enough to hold
112 : // CMSG_SPACE(Channel::kReadBufferSize) bytes (see the comment below for an
113 : // explanation of where Channel::kReadBufferSize comes from). However,
114 : // CMSG_SPACE is apparently not a constant on Macs, so we can't use it in the
115 : // array size. Consequently, we pick a number here that is at least
116 : // CMSG_SPACE(0) on all platforms. And we assert at runtime, in
117 : // Channel::ChannelImpl::Init, that it's big enough.
118 : enum {
119 : kControlBufferSlopBytes = 32
120 : };
121 :
122 : // This is a control message buffer large enough to hold all the file
123 : // descriptors that will be read in when reading Channel::kReadBufferSize
124 : // bytes of data. Message::WriteFileDescriptor always writes one word of
125 : // data for every file descriptor added to the message, so kReadBufferSize
126 : // bytes of data can never be accompanied by more than
127 : // kReadBufferSize / sizeof(int) file descriptors. Since a file descriptor
128 : // takes sizeof(int) bytes, the control buffer must be
129 : // Channel::kReadBufferSize bytes. We add kControlBufferSlopBytes bytes
130 : // for the control header.
131 : char input_cmsg_buf_[Channel::kReadBufferSize + kControlBufferSlopBytes];
132 :
133 : // Large incoming messages that span multiple pipe buffers get built-up in the
134 : // buffers of this message.
135 : mozilla::Maybe<Message> incoming_message_;
136 : std::vector<int> input_overflow_fds_;
137 :
138 : // In server-mode, we have to wait for the client to connect before we
139 : // can begin reading. We make use of the input_state_ when performing
140 : // the connect operation in overlapped mode.
141 : bool waiting_connect_;
142 :
143 : // This flag is set when processing incoming messages. It is used to
144 : // avoid recursing through ProcessIncomingMessages, which could cause
145 : // problems. TODO(darin): make this unnecessary
146 : bool processing_incoming_;
147 :
148 : // This flag is set after we've closed the channel.
149 : bool closed_;
150 :
151 : #if defined(OS_MACOSX)
152 : struct PendingDescriptors {
153 : uint32_t id;
154 : RefPtr<FileDescriptorSet> fds;
155 :
156 : PendingDescriptors() : id(0) { }
157 : PendingDescriptors(uint32_t id, FileDescriptorSet *fds)
158 : : id(id),
159 : fds(fds)
160 : { }
161 : };
162 :
163 : std::list<PendingDescriptors> pending_fds_;
164 :
165 : // A generation ID for RECEIVED_FD messages.
166 : uint32_t last_pending_fd_id_;
167 : #endif
168 :
169 : // This variable is updated so it matches output_queue_.size(), except we can
170 : // read output_queue_length_ from any thread (if we're OK getting an
171 : // occasional out-of-date or bogus value). We use output_queue_length_ to
172 : // implement Unsound_NumQueuedMessages.
173 : size_t output_queue_length_;
174 :
175 : ScopedRunnableMethodFactory<ChannelImpl> factory_;
176 :
177 : DISALLOW_COPY_AND_ASSIGN(ChannelImpl);
178 : };
179 :
180 : } // namespace IPC
181 :
182 : #endif // CHROME_COMMON_IPC_CHANNEL_POSIX_H_
|