[email protected] | 456b0ea | 2012-03-30 19:57:22 | [diff] [blame] | 1 | // Copyright (c) 2012 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 | #include "ipc/ipc_channel_nacl.h" |
| 6 | |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 7 | #include <errno.h> |
| 8 | #include <stddef.h> |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 9 | #include <sys/types.h> |
| 10 | |
| 11 | #include <algorithm> |
| 12 | |
| 13 | #include "base/bind.h" |
[email protected] | 456b0ea | 2012-03-30 19:57:22 | [diff] [blame] | 14 | #include "base/logging.h" |
skyostil | e687bdff | 2015-05-12 11:29:21 | [diff] [blame] | 15 | #include "base/single_thread_task_runner.h" |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 16 | #include "base/synchronization/lock.h" |
| 17 | #include "base/task_runner_util.h" |
skyostil | e687bdff | 2015-05-12 11:29:21 | [diff] [blame] | 18 | #include "base/thread_task_runner_handle.h" |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 19 | #include "base/threading/simple_thread.h" |
[email protected] | 7e3d752 | 2014-03-20 21:00:50 | [diff] [blame] | 20 | #include "ipc/ipc_listener.h" |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 21 | #include "ipc/ipc_logging.h" |
morrita | 4b5c28e2 | 2015-01-14 21:17:06 | [diff] [blame] | 22 | #include "ipc/ipc_message_attachment_set.h" |
[email protected] | 18ff3c3 | 2013-06-05 23:37:11 | [diff] [blame] | 23 | #include "native_client/src/public/imc_syscalls.h" |
| 24 | #include "native_client/src/public/imc_types.h" |
[email protected] | 456b0ea | 2012-03-30 19:57:22 | [diff] [blame] | 25 | |
| 26 | namespace IPC { |
[email protected] | ff79fa2 | 2012-07-10 17:26:03 | [diff] [blame] | 27 | |
| 28 | struct MessageContents { |
| 29 | std::vector<char> data; |
| 30 | std::vector<int> fds; |
| 31 | }; |
| 32 | |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 33 | namespace { |
| 34 | |
[email protected] | ff79fa2 | 2012-07-10 17:26:03 | [diff] [blame] | 35 | bool ReadDataOnReaderThread(int pipe, MessageContents* contents) { |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 36 | DCHECK(pipe >= 0); |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 37 | if (pipe < 0) |
[email protected] | ff79fa2 | 2012-07-10 17:26:03 | [diff] [blame] | 38 | return false; |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 39 | |
[email protected] | ff79fa2 | 2012-07-10 17:26:03 | [diff] [blame] | 40 | contents->data.resize(Channel::kReadBufferSize); |
yusukes | eaa3c5bf | 2015-03-17 00:34:13 | [diff] [blame] | 41 | contents->fds.resize(NACL_ABI_IMC_DESC_MAX); |
[email protected] | ff79fa2 | 2012-07-10 17:26:03 | [diff] [blame] | 42 | |
[email protected] | 18ff3c3 | 2013-06-05 23:37:11 | [diff] [blame] | 43 | NaClAbiNaClImcMsgIoVec iov = { &contents->data[0], contents->data.size() }; |
| 44 | NaClAbiNaClImcMsgHdr msg = { |
| 45 | &iov, 1, &contents->fds[0], contents->fds.size() |
| 46 | }; |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 47 | |
| 48 | int bytes_read = imc_recvmsg(pipe, &msg, 0); |
| 49 | |
| 50 | if (bytes_read <= 0) { |
| 51 | // NaClIPCAdapter::BlockingReceive returns -1 when the pipe closes (either |
| 52 | // due to error or for regular shutdown). |
[email protected] | ff79fa2 | 2012-07-10 17:26:03 | [diff] [blame] | 53 | contents->data.clear(); |
| 54 | contents->fds.clear(); |
| 55 | return false; |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 56 | } |
| 57 | DCHECK(bytes_read); |
[email protected] | ff79fa2 | 2012-07-10 17:26:03 | [diff] [blame] | 58 | // Resize the buffers down to the number of bytes and fds we actually read. |
| 59 | contents->data.resize(bytes_read); |
| 60 | contents->fds.resize(msg.desc_length); |
| 61 | return true; |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 62 | } |
| 63 | |
| 64 | } // namespace |
| 65 | |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 66 | class ChannelNacl::ReaderThreadRunner |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 67 | : public base::DelegateSimpleThread::Delegate { |
| 68 | public: |
| 69 | // |pipe|: A file descriptor from which we will read using imc_recvmsg. |
| 70 | // |data_read_callback|: A callback we invoke (on the main thread) when we |
[email protected] | ff79fa2 | 2012-07-10 17:26:03 | [diff] [blame] | 71 | // have read data. |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 72 | // |failure_callback|: A callback we invoke when we have a failure reading |
| 73 | // from |pipe|. |
| 74 | // |main_message_loop|: A proxy for the main thread, where we will invoke the |
| 75 | // above callbacks. |
| 76 | ReaderThreadRunner( |
| 77 | int pipe, |
skyostil | e687bdff | 2015-05-12 11:29:21 | [diff] [blame] | 78 | base::Callback<void(scoped_ptr<MessageContents>)> data_read_callback, |
| 79 | base::Callback<void()> failure_callback, |
| 80 | scoped_refptr<base::SingleThreadTaskRunner> main_task_runner); |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 81 | |
| 82 | // DelegateSimpleThread implementation. Reads data from the pipe in a loop |
| 83 | // until either we are told to quit or a read fails. |
nick | d60f717 | 2015-04-23 16:42:48 | [diff] [blame] | 84 | void Run() override; |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 85 | |
| 86 | private: |
| 87 | int pipe_; |
[email protected] | ff79fa2 | 2012-07-10 17:26:03 | [diff] [blame] | 88 | base::Callback<void (scoped_ptr<MessageContents>)> data_read_callback_; |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 89 | base::Callback<void ()> failure_callback_; |
skyostil | e687bdff | 2015-05-12 11:29:21 | [diff] [blame] | 90 | scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 91 | |
| 92 | DISALLOW_COPY_AND_ASSIGN(ReaderThreadRunner); |
| 93 | }; |
| 94 | |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 95 | ChannelNacl::ReaderThreadRunner::ReaderThreadRunner( |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 96 | int pipe, |
skyostil | e687bdff | 2015-05-12 11:29:21 | [diff] [blame] | 97 | base::Callback<void(scoped_ptr<MessageContents>)> data_read_callback, |
| 98 | base::Callback<void()> failure_callback, |
| 99 | scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 100 | : pipe_(pipe), |
| 101 | data_read_callback_(data_read_callback), |
| 102 | failure_callback_(failure_callback), |
skyostil | e687bdff | 2015-05-12 11:29:21 | [diff] [blame] | 103 | main_task_runner_(main_task_runner) { |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 104 | } |
| 105 | |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 106 | void ChannelNacl::ReaderThreadRunner::Run() { |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 107 | while (true) { |
[email protected] | ff79fa2 | 2012-07-10 17:26:03 | [diff] [blame] | 108 | scoped_ptr<MessageContents> msg_contents(new MessageContents); |
| 109 | bool success = ReadDataOnReaderThread(pipe_, msg_contents.get()); |
| 110 | if (success) { |
skyostil | e687bdff | 2015-05-12 11:29:21 | [diff] [blame] | 111 | main_task_runner_->PostTask( |
| 112 | FROM_HERE, |
[email protected] | d873f19 | 2013-01-23 02:20:35 | [diff] [blame] | 113 | base::Bind(data_read_callback_, base::Passed(&msg_contents))); |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 114 | } else { |
skyostil | e687bdff | 2015-05-12 11:29:21 | [diff] [blame] | 115 | main_task_runner_->PostTask(FROM_HERE, failure_callback_); |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 116 | // Because the read failed, we know we're going to quit. Don't bother |
| 117 | // trying to read again. |
| 118 | return; |
| 119 | } |
| 120 | } |
| 121 | } |
[email protected] | 456b0ea | 2012-03-30 19:57:22 | [diff] [blame] | 122 | |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 123 | ChannelNacl::ChannelNacl(const IPC::ChannelHandle& channel_handle, |
| 124 | Mode mode, |
erikchen | 27aa7d8 | 2015-06-16 21:21:04 | [diff] [blame] | 125 | Listener* listener, |
| 126 | AttachmentBroker* broker) |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 127 | : ChannelReader(listener), |
| 128 | mode_(mode), |
| 129 | waiting_connect_(true), |
| 130 | pipe_(-1), |
| 131 | pipe_name_(channel_handle.name), |
erikchen | 27aa7d8 | 2015-06-16 21:21:04 | [diff] [blame] | 132 | weak_ptr_factory_(this), |
| 133 | broker_(broker) { |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 134 | if (!CreatePipe(channel_handle)) { |
| 135 | // The pipe may have been closed already. |
| 136 | const char *modestr = (mode_ & MODE_SERVER_FLAG) ? "server" : "client"; |
| 137 | LOG(WARNING) << "Unable to create pipe named \"" << channel_handle.name |
| 138 | << "\" in " << modestr << " mode"; |
| 139 | } |
[email protected] | 456b0ea | 2012-03-30 19:57:22 | [diff] [blame] | 140 | } |
| 141 | |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 142 | ChannelNacl::~ChannelNacl() { |
[email protected] | 456b0ea | 2012-03-30 19:57:22 | [diff] [blame] | 143 | Close(); |
| 144 | } |
| 145 | |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 146 | base::ProcessId ChannelNacl::GetPeerPID() const { |
[email protected] | 7e3d752 | 2014-03-20 21:00:50 | [diff] [blame] | 147 | // This shouldn't actually get used in the untrusted side of the proxy, and we |
| 148 | // don't have the real pid anyway. |
| 149 | return -1; |
| 150 | } |
| 151 | |
[email protected] | 6486088 | 2014-08-04 23:44:17 | [diff] [blame] | 152 | base::ProcessId ChannelNacl::GetSelfPID() const { |
| 153 | return -1; |
| 154 | } |
| 155 | |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 156 | bool ChannelNacl::Connect() { |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 157 | if (pipe_ == -1) { |
[email protected] | 7e3d752 | 2014-03-20 21:00:50 | [diff] [blame] | 158 | DLOG(WARNING) << "Channel creation failed: " << pipe_name_; |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 159 | return false; |
| 160 | } |
| 161 | |
[email protected] | cf0e7ee | 2012-07-11 00:49:17 | [diff] [blame] | 162 | // Note that Connect is called on the "Channel" thread (i.e., the same thread |
| 163 | // where Channel::Send will be called, and the same thread that should receive |
| 164 | // messages). The constructor might be invoked on another thread (see |
| 165 | // ChannelProxy for an example of that). Therefore, we must wait until Connect |
skyostil | e687bdff | 2015-05-12 11:29:21 | [diff] [blame] | 166 | // is called to decide which SingleThreadTaskRunner to pass to |
| 167 | // ReaderThreadRunner. |
| 168 | reader_thread_runner_.reset(new ReaderThreadRunner( |
| 169 | pipe_, |
| 170 | base::Bind(&ChannelNacl::DidRecvMsg, weak_ptr_factory_.GetWeakPtr()), |
| 171 | base::Bind(&ChannelNacl::ReadDidFail, weak_ptr_factory_.GetWeakPtr()), |
| 172 | base::ThreadTaskRunnerHandle::Get())); |
[email protected] | cf0e7ee | 2012-07-11 00:49:17 | [diff] [blame] | 173 | reader_thread_.reset( |
| 174 | new base::DelegateSimpleThread(reader_thread_runner_.get(), |
| 175 | "ipc_channel_nacl reader thread")); |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 176 | reader_thread_->Start(); |
| 177 | waiting_connect_ = false; |
| 178 | // If there were any messages queued before connection, send them. |
| 179 | ProcessOutgoingMessages(); |
skyostil | e687bdff | 2015-05-12 11:29:21 | [diff] [blame] | 180 | base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 181 | FROM_HERE, base::Bind(&ChannelNacl::CallOnChannelConnected, |
| 182 | weak_ptr_factory_.GetWeakPtr())); |
[email protected] | 7e3d752 | 2014-03-20 21:00:50 | [diff] [blame] | 183 | |
[email protected] | 5ce038b | 2012-06-06 18:14:56 | [diff] [blame] | 184 | return true; |
[email protected] | 456b0ea | 2012-03-30 19:57:22 | [diff] [blame] | 185 | } |
| 186 | |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 187 | void ChannelNacl::Close() { |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 188 | // For now, we assume that at shutdown, the reader thread will be woken with |
| 189 | // a failure (see NaClIPCAdapter::BlockingRead and CloseChannel). Or... we |
| 190 | // might simply be killed with no chance to clean up anyway :-). |
| 191 | // If untrusted code tries to close the channel prior to shutdown, it's likely |
| 192 | // to hang. |
| 193 | // TODO(dmichael): Can we do anything smarter here to make sure the reader |
| 194 | // thread wakes up and quits? |
| 195 | reader_thread_->Join(); |
| 196 | close(pipe_); |
| 197 | pipe_ = -1; |
| 198 | reader_thread_runner_.reset(); |
| 199 | reader_thread_.reset(); |
| 200 | read_queue_.clear(); |
| 201 | output_queue_.clear(); |
[email protected] | 456b0ea | 2012-03-30 19:57:22 | [diff] [blame] | 202 | } |
| 203 | |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 204 | bool ChannelNacl::Send(Message* message) { |
morrita | 81b17e0 | 2015-02-06 00:58:30 | [diff] [blame] | 205 | DCHECK(!message->HasAttachments()); |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 206 | DVLOG(2) << "sending message @" << message << " on channel @" << this |
| 207 | << " with type " << message->type(); |
| 208 | scoped_ptr<Message> message_ptr(message); |
| 209 | |
| 210 | #ifdef IPC_MESSAGE_LOG_ENABLED |
[email protected] | 19d3a3e | 2012-06-11 18:18:33 | [diff] [blame] | 211 | Logging::GetInstance()->OnSendMessage(message_ptr.get(), ""); |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 212 | #endif // IPC_MESSAGE_LOG_ENABLED |
| 213 | |
[email protected] | 2c391df | 2012-09-18 03:41:29 | [diff] [blame] | 214 | message->TraceMessageBegin(); |
[email protected] | 19d3a3e | 2012-06-11 18:18:33 | [diff] [blame] | 215 | output_queue_.push_back(linked_ptr<Message>(message_ptr.release())); |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 216 | if (!waiting_connect_) |
| 217 | return ProcessOutgoingMessages(); |
| 218 | |
| 219 | return true; |
[email protected] | 456b0ea | 2012-03-30 19:57:22 | [diff] [blame] | 220 | } |
| 221 | |
erikchen | 27aa7d8 | 2015-06-16 21:21:04 | [diff] [blame] | 222 | AttachmentBroker* ChannelNacl::GetAttachmentBroker() { |
| 223 | return broker_; |
| 224 | } |
| 225 | |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 226 | void ChannelNacl::DidRecvMsg(scoped_ptr<MessageContents> contents) { |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 227 | // Close sets the pipe to -1. It's possible we'll get a buffer sent to us from |
| 228 | // the reader thread after Close is called. If so, we ignore it. |
| 229 | if (pipe_ == -1) |
| 230 | return; |
| 231 | |
[email protected] | ff79fa2 | 2012-07-10 17:26:03 | [diff] [blame] | 232 | linked_ptr<std::vector<char> > data(new std::vector<char>); |
| 233 | data->swap(contents->data); |
| 234 | read_queue_.push_back(data); |
| 235 | |
| 236 | input_fds_.insert(input_fds_.end(), |
| 237 | contents->fds.begin(), contents->fds.end()); |
| 238 | contents->fds.clear(); |
[email protected] | dbbe276b | 2012-06-06 21:47:57 | [diff] [blame] | 239 | |
| 240 | // In POSIX, we would be told when there are bytes to read by implementing |
| 241 | // OnFileCanReadWithoutBlocking in MessageLoopForIO::Watcher. In NaCl, we |
| 242 | // instead know at this point because the reader thread posted some data to |
| 243 | // us. |
| 244 | ProcessIncomingMessages(); |
[email protected] | 456b0ea | 2012-03-30 19:57:22 | [diff] [blame] | 245 | } |
| 246 | |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 247 | void ChannelNacl::ReadDidFail() { |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 248 | Close(); |
[email protected] | 456b0ea | 2012-03-30 19:57:22 | [diff] [blame] | 249 | } |
| 250 | |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 251 | bool ChannelNacl::CreatePipe( |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 252 | const IPC::ChannelHandle& channel_handle) { |
| 253 | DCHECK(pipe_ == -1); |
| 254 | |
| 255 | // There's one possible case in NaCl: |
| 256 | // 1) It's a channel wrapping a pipe that is given to us. |
| 257 | // We don't support these: |
| 258 | // 2) It's for a named channel. |
| 259 | // 3) It's for a client that we implement ourself. |
| 260 | // 4) It's the initial IPC channel. |
| 261 | |
| 262 | if (channel_handle.socket.fd == -1) { |
| 263 | NOTIMPLEMENTED(); |
| 264 | return false; |
| 265 | } |
| 266 | pipe_ = channel_handle.socket.fd; |
| 267 | return true; |
[email protected] | 456b0ea | 2012-03-30 19:57:22 | [diff] [blame] | 268 | } |
| 269 | |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 270 | bool ChannelNacl::ProcessOutgoingMessages() { |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 271 | DCHECK(!waiting_connect_); // Why are we trying to send messages if there's |
| 272 | // no connection? |
| 273 | if (output_queue_.empty()) |
| 274 | return true; |
| 275 | |
| 276 | if (pipe_ == -1) |
| 277 | return false; |
| 278 | |
| 279 | // Write out all the messages. The trusted implementation is guaranteed to not |
| 280 | // block. See NaClIPCAdapter::Send for the implementation of imc_sendmsg. |
| 281 | while (!output_queue_.empty()) { |
| 282 | linked_ptr<Message> msg = output_queue_.front(); |
| 283 | output_queue_.pop_front(); |
| 284 | |
morrita | 4b5c28e2 | 2015-01-14 21:17:06 | [diff] [blame] | 285 | int fds[MessageAttachmentSet::kMaxDescriptorsPerMessage]; |
| 286 | const size_t num_fds = msg->attachment_set()->size(); |
| 287 | DCHECK(num_fds <= MessageAttachmentSet::kMaxDescriptorsPerMessage); |
| 288 | msg->attachment_set()->PeekDescriptors(fds); |
[email protected] | ff79fa2 | 2012-07-10 17:26:03 | [diff] [blame] | 289 | |
[email protected] | 18ff3c3 | 2013-06-05 23:37:11 | [diff] [blame] | 290 | NaClAbiNaClImcMsgIoVec iov = { |
| 291 | const_cast<void*>(msg->data()), msg->size() |
| 292 | }; |
| 293 | NaClAbiNaClImcMsgHdr msgh = { &iov, 1, fds, num_fds }; |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 294 | ssize_t bytes_written = imc_sendmsg(pipe_, &msgh, 0); |
| 295 | |
[email protected] | ff79fa2 | 2012-07-10 17:26:03 | [diff] [blame] | 296 | DCHECK(bytes_written); // The trusted side shouldn't return 0. |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 297 | if (bytes_written < 0) { |
| 298 | // The trusted side should only ever give us an error of EPIPE. We |
| 299 | // should never be interrupted, nor should we get EAGAIN. |
| 300 | DCHECK(errno == EPIPE); |
| 301 | Close(); |
| 302 | PLOG(ERROR) << "pipe_ error on " |
| 303 | << pipe_ |
| 304 | << " Currently writing message of size: " |
| 305 | << msg->size(); |
| 306 | return false; |
[email protected] | ff79fa2 | 2012-07-10 17:26:03 | [diff] [blame] | 307 | } else { |
morrita | 4b5c28e2 | 2015-01-14 21:17:06 | [diff] [blame] | 308 | msg->attachment_set()->CommitAll(); |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 309 | } |
| 310 | |
| 311 | // Message sent OK! |
| 312 | DVLOG(2) << "sent message @" << msg.get() << " with type " << msg->type() |
| 313 | << " on fd " << pipe_; |
| 314 | } |
| 315 | return true; |
[email protected] | 456b0ea | 2012-03-30 19:57:22 | [diff] [blame] | 316 | } |
| 317 | |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 318 | void ChannelNacl::CallOnChannelConnected() { |
| 319 | listener()->OnChannelConnected(GetPeerPID()); |
[email protected] | 7e3d752 | 2014-03-20 21:00:50 | [diff] [blame] | 320 | } |
| 321 | |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 322 | ChannelNacl::ReadState ChannelNacl::ReadData( |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 323 | char* buffer, |
| 324 | int buffer_len, |
| 325 | int* bytes_read) { |
| 326 | *bytes_read = 0; |
| 327 | if (pipe_ == -1) |
| 328 | return READ_FAILED; |
| 329 | if (read_queue_.empty()) |
| 330 | return READ_PENDING; |
| 331 | while (!read_queue_.empty() && *bytes_read < buffer_len) { |
| 332 | linked_ptr<std::vector<char> > vec(read_queue_.front()); |
[email protected] | 74ca23f | 2012-09-24 04:49:10 | [diff] [blame] | 333 | size_t bytes_to_read = buffer_len - *bytes_read; |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 334 | if (vec->size() <= bytes_to_read) { |
| 335 | // We can read and discard the entire vector. |
| 336 | std::copy(vec->begin(), vec->end(), buffer + *bytes_read); |
| 337 | *bytes_read += vec->size(); |
| 338 | read_queue_.pop_front(); |
| 339 | } else { |
| 340 | // Read all the bytes we can and discard them from the front of the |
| 341 | // vector. (This can be slowish, since erase has to move the back of the |
| 342 | // vector to the front, but it's hopefully a temporary hack and it keeps |
| 343 | // the code simple). |
| 344 | std::copy(vec->begin(), vec->begin() + bytes_to_read, |
| 345 | buffer + *bytes_read); |
| 346 | vec->erase(vec->begin(), vec->begin() + bytes_to_read); |
| 347 | *bytes_read += bytes_to_read; |
| 348 | } |
| 349 | } |
| 350 | return READ_SUCCEEDED; |
[email protected] | fe5d406 | 2012-04-23 21:18:19 | [diff] [blame] | 351 | } |
| 352 | |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 353 | bool ChannelNacl::WillDispatchInputMessage(Message* msg) { |
[email protected] | ff79fa2 | 2012-07-10 17:26:03 | [diff] [blame] | 354 | uint16 header_fds = msg->header()->num_fds; |
| 355 | CHECK(header_fds == input_fds_.size()); |
| 356 | if (header_fds == 0) |
| 357 | return true; // Nothing to do. |
| 358 | |
| 359 | // The shenaniganery below with &foo.front() requires input_fds_ to have |
| 360 | // contiguous underlying storage (such as a simple array or a std::vector). |
| 361 | // This is why the header warns not to make input_fds_ a deque<>. |
morrita | 4b5c28e2 | 2015-01-14 21:17:06 | [diff] [blame] | 362 | msg->attachment_set()->AddDescriptorsToOwn(&input_fds_.front(), header_fds); |
[email protected] | ff79fa2 | 2012-07-10 17:26:03 | [diff] [blame] | 363 | input_fds_.clear(); |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 364 | return true; |
[email protected] | fe5d406 | 2012-04-23 21:18:19 | [diff] [blame] | 365 | } |
| 366 | |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 367 | bool ChannelNacl::DidEmptyInputBuffers() { |
[email protected] | ff79fa2 | 2012-07-10 17:26:03 | [diff] [blame] | 368 | // When the input data buffer is empty, the fds should be too. |
| 369 | return input_fds_.empty(); |
[email protected] | fe5d406 | 2012-04-23 21:18:19 | [diff] [blame] | 370 | } |
| 371 | |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 372 | void ChannelNacl::HandleInternalMessage(const Message& msg) { |
[email protected] | 4e8f0a76 | 2012-05-31 19:37:54 | [diff] [blame] | 373 | // The trusted side IPC::Channel should handle the "hello" handshake; we |
| 374 | // should not receive the "Hello" message. |
| 375 | NOTREACHED(); |
[email protected] | 456b0ea | 2012-03-30 19:57:22 | [diff] [blame] | 376 | } |
| 377 | |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 378 | // Channel's methods |
[email protected] | 456b0ea | 2012-03-30 19:57:22 | [diff] [blame] | 379 | |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 380 | // static |
erikchen | 27aa7d8 | 2015-06-16 21:21:04 | [diff] [blame] | 381 | scoped_ptr<Channel> Channel::Create(const IPC::ChannelHandle& channel_handle, |
| 382 | Mode mode, |
| 383 | Listener* listener, |
| 384 | AttachmentBroker* broker) { |
[email protected] | 2f60c9b | 2014-06-06 20:13:51 | [diff] [blame] | 385 | return scoped_ptr<Channel>( |
erikchen | 27aa7d8 | 2015-06-16 21:21:04 | [diff] [blame] | 386 | new ChannelNacl(channel_handle, mode, listener, broker)); |
[email protected] | 456b0ea | 2012-03-30 19:57:22 | [diff] [blame] | 387 | } |
| 388 | |
[email protected] | 456b0ea | 2012-03-30 19:57:22 | [diff] [blame] | 389 | } // namespace IPC |