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 |