| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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_reader.h" | 5 #include "ipc/ipc_channel_reader.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "ipc/ipc_listener.h" | 9 #include "ipc/ipc_listener.h" |
| 10 #include "ipc/ipc_logging.h" | 10 #include "ipc/ipc_logging.h" |
| 11 #include "ipc/ipc_message.h" | 11 #include "ipc/ipc_message.h" |
| 12 #include "ipc/ipc_message_attachment_set.h" | 12 #include "ipc/ipc_message_attachment_set.h" |
| 13 #include "ipc/ipc_message_macros.h" | 13 #include "ipc/ipc_message_macros.h" |
| 14 | 14 |
| 15 namespace IPC { | 15 namespace IPC { |
| 16 namespace internal { | 16 namespace internal { |
| 17 | 17 |
| 18 ChannelReader::ChannelReader(Listener* listener) : listener_(listener) { | 18 ChannelReader::ChannelReader(Listener* listener) |
| 19 : listener_(listener), |
| 20 max_input_buffer_size_(Channel::kMaximumReadBufferSize) { |
| 19 memset(input_buf_, 0, sizeof(input_buf_)); | 21 memset(input_buf_, 0, sizeof(input_buf_)); |
| 20 } | 22 } |
| 21 | 23 |
| 22 ChannelReader::~ChannelReader() { | 24 ChannelReader::~ChannelReader() { |
| 23 DCHECK(blocked_ids_.empty()); | 25 DCHECK(blocked_ids_.empty()); |
| 24 } | 26 } |
| 25 | 27 |
| 26 ChannelReader::DispatchState ChannelReader::ProcessIncomingMessages() { | 28 ChannelReader::DispatchState ChannelReader::ProcessIncomingMessages() { |
| 27 while (true) { | 29 while (true) { |
| 28 int bytes_read = 0; | 30 int bytes_read = 0; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 p = info.message_end; | 109 p = info.message_end; |
| 108 } else { | 110 } else { |
| 109 // Last message is partial. | 111 // Last message is partial. |
| 110 next_message_size = info.message_size; | 112 next_message_size = info.message_size; |
| 111 if (!CheckMessageSize(next_message_size)) | 113 if (!CheckMessageSize(next_message_size)) |
| 112 return false; | 114 return false; |
| 113 break; | 115 break; |
| 114 } | 116 } |
| 115 } | 117 } |
| 116 | 118 |
| 119 // Account for the case where last message's byte is in the next data chunk. |
| 120 size_t next_message_buffer_size = next_message_size ? |
| 121 next_message_size + Channel::kReadBufferSize - 1: |
| 122 0; |
| 123 |
| 117 // Save any partial data in the overflow buffer. | 124 // Save any partial data in the overflow buffer. |
| 118 input_overflow_buf_.assign(p, end - p); | 125 input_overflow_buf_.assign(p, end - p); |
| 119 | 126 |
| 120 if (!input_overflow_buf_.empty()) { | 127 if (!input_overflow_buf_.empty()) { |
| 121 // We have something in the overflow buffer, which means that we will | 128 // We have something in the overflow buffer, which means that we will |
| 122 // append the next data chunk (instead of parsing it directly). So we | 129 // append the next data chunk (instead of parsing it directly). So we |
| 123 // resize the buffer to fit the next message, to avoid repeatedly | 130 // resize the buffer to fit the next message, to avoid repeatedly |
| 124 // growing the buffer as we receive all message' data chunks. | 131 // growing the buffer as we receive all message' data chunks. |
| 125 next_message_size += Channel::kReadBufferSize - 1; | 132 if (next_message_buffer_size > input_overflow_buf_.capacity()) { |
| 126 if (next_message_size > input_overflow_buf_.capacity()) { | 133 input_overflow_buf_.reserve(next_message_buffer_size); |
| 127 input_overflow_buf_.reserve(next_message_size); | |
| 128 } | 134 } |
| 129 } | 135 } |
| 130 | 136 |
| 137 // Trim the buffer if we can |
| 138 if (next_message_buffer_size < max_input_buffer_size_ && |
| 139 input_overflow_buf_.size() < max_input_buffer_size_ && |
| 140 input_overflow_buf_.capacity() > max_input_buffer_size_) { |
| 141 // std::string doesn't really have a method to shrink capacity to |
| 142 // a specific value, so we have to swap with another string. |
| 143 std::string trimmed_buf; |
| 144 trimmed_buf.reserve(max_input_buffer_size_); |
| 145 if (trimmed_buf.capacity() > max_input_buffer_size_) { |
| 146 // Since we don't control how much space reserve() actually reserves, |
| 147 // we have to go other way around and change the max size to avoid |
| 148 // getting into the outer if() again. |
| 149 max_input_buffer_size_ = trimmed_buf.capacity(); |
| 150 } |
| 151 trimmed_buf.assign(input_overflow_buf_.data(), |
| 152 input_overflow_buf_.size()); |
| 153 input_overflow_buf_.swap(trimmed_buf); |
| 154 } |
| 155 |
| 131 if (input_overflow_buf_.empty() && !DidEmptyInputBuffers()) | 156 if (input_overflow_buf_.empty() && !DidEmptyInputBuffers()) |
| 132 return false; | 157 return false; |
| 133 return true; | 158 return true; |
| 134 } | 159 } |
| 135 | 160 |
| 136 bool ChannelReader::HandleTranslatedMessage( | 161 bool ChannelReader::HandleTranslatedMessage( |
| 137 Message* translated_message, | 162 Message* translated_message, |
| 138 const AttachmentIdVector& attachment_ids) { | 163 const AttachmentIdVector& attachment_ids) { |
| 139 | 164 |
| 140 // Immediately handle internal messages. | 165 // Immediately handle internal messages. |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 if (size <= Channel::kMaximumMessageSize) { | 324 if (size <= Channel::kMaximumMessageSize) { |
| 300 return true; | 325 return true; |
| 301 } | 326 } |
| 302 input_overflow_buf_.clear(); | 327 input_overflow_buf_.clear(); |
| 303 LOG(ERROR) << "IPC message is too big: " << size; | 328 LOG(ERROR) << "IPC message is too big: " << size; |
| 304 return false; | 329 return false; |
| 305 } | 330 } |
| 306 | 331 |
| 307 } // namespace internal | 332 } // namespace internal |
| 308 } // namespace IPC | 333 } // namespace IPC |
| OLD | NEW |