| 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 "net/quic/quic_stream_sequencer.h" | 5 #include "net/quic/quic_stream_sequencer.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 | 9 |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 // Silently ignore duplicates. | 75 // Silently ignore duplicates. |
| 76 return true; | 76 return true; |
| 77 } | 77 } |
| 78 | 78 |
| 79 QuicStreamOffset byte_offset = frame.offset; | 79 QuicStreamOffset byte_offset = frame.offset; |
| 80 const char* data = frame.data.data(); | 80 const char* data = frame.data.data(); |
| 81 size_t data_len = frame.data.size(); | 81 size_t data_len = frame.data.size(); |
| 82 | 82 |
| 83 if (byte_offset == num_bytes_consumed_) { | 83 if (byte_offset == num_bytes_consumed_) { |
| 84 DVLOG(1) << "Processing byte offset " << byte_offset; | 84 DVLOG(1) << "Processing byte offset " << byte_offset; |
| 85 size_t bytes_consumed = stream_->ProcessData(data, data_len); | 85 size_t bytes_consumed = stream_->ProcessRawData(data, data_len); |
| 86 num_bytes_consumed_ += bytes_consumed; | 86 num_bytes_consumed_ += bytes_consumed; |
| 87 | 87 |
| 88 if (MaybeCloseStream()) { | 88 if (MaybeCloseStream()) { |
| 89 return true; | 89 return true; |
| 90 } | 90 } |
| 91 if (bytes_consumed > data_len) { | 91 if (bytes_consumed > data_len) { |
| 92 stream_->Close(QUIC_SERVER_ERROR_PROCESSING_STREAM); | 92 stream_->Close(QUIC_SERVER_ERROR_PROCESSING_STREAM); |
| 93 return false; | 93 return false; |
| 94 } else if (bytes_consumed == data_len) { | 94 } else if (bytes_consumed == data_len) { |
| 95 FlushBufferedFrames(); | 95 FlushBufferedFrames(); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 << num_bytes_consumed_ << " of " << close_offset_ | 132 << num_bytes_consumed_ << " of " << close_offset_ |
| 133 << " bytes."; | 133 << " bytes."; |
| 134 // Technically it's an error if num_bytes_consumed isn't exactly | 134 // Technically it's an error if num_bytes_consumed isn't exactly |
| 135 // equal, but error handling seems silly at this point. | 135 // equal, but error handling seems silly at this point. |
| 136 stream_->TerminateFromPeer(half_close_); | 136 stream_->TerminateFromPeer(half_close_); |
| 137 return true; | 137 return true; |
| 138 } | 138 } |
| 139 return false; | 139 return false; |
| 140 } | 140 } |
| 141 | 141 |
| 142 int QuicStreamSequencer::GetReadableRegions(iovec* iov, int iov_len) { |
| 143 FrameMap::iterator it = frames_.begin(); |
| 144 int index = 0; |
| 145 uint64 offset = num_bytes_consumed_; |
| 146 while (it != frames_.end() && index < iov_len) { |
| 147 if (it->first != offset) return index; |
| 148 |
| 149 iov[index].iov_base = static_cast<void*>( |
| 150 const_cast<char*>(it->second.data())); |
| 151 iov[index].iov_len = it->second.size(); |
| 152 offset += it->second.size(); |
| 153 |
| 154 ++index; |
| 155 ++it; |
| 156 } |
| 157 return index; |
| 158 } |
| 159 |
| 160 int QuicStreamSequencer::Readv(const struct iovec* iov, int iov_len) { |
| 161 FrameMap::iterator it = frames_.begin(); |
| 162 int iov_index = 0; |
| 163 size_t iov_offset = 0; |
| 164 size_t frame_offset = 0; |
| 165 size_t initial_bytes_consumed = num_bytes_consumed_; |
| 166 |
| 167 while (iov_index < iov_len && |
| 168 it != frames_.end() && |
| 169 it->first == num_bytes_consumed_) { |
| 170 int bytes_to_read = min(iov[iov_index].iov_len - iov_offset, |
| 171 it->second.size() - frame_offset); |
| 172 |
| 173 char* iov_ptr = static_cast<char*>(iov[iov_index].iov_base) + iov_offset; |
| 174 memcpy(iov_ptr, |
| 175 it->second.data() + frame_offset, bytes_to_read); |
| 176 frame_offset += bytes_to_read; |
| 177 iov_offset += bytes_to_read; |
| 178 |
| 179 if (iov[iov_index].iov_len == iov_offset) { |
| 180 // We've filled this buffer. |
| 181 iov_offset = 0; |
| 182 ++iov_index; |
| 183 } |
| 184 if (it->second.size() == frame_offset) { |
| 185 // We've copied this whole frame |
| 186 num_bytes_consumed_ += it->second.size(); |
| 187 frames_.erase(it); |
| 188 it = frames_.begin(); |
| 189 frame_offset = 0; |
| 190 } |
| 191 } |
| 192 // We've finished copying. If we have a partial frame, update it. |
| 193 if (frame_offset != 0) { |
| 194 frames_.insert(make_pair(it->first + frame_offset, |
| 195 it->second.substr(frame_offset))); |
| 196 frames_.erase(frames_.begin()); |
| 197 num_bytes_consumed_ += frame_offset; |
| 198 } |
| 199 return num_bytes_consumed_ - initial_bytes_consumed; |
| 200 } |
| 201 |
| 202 void QuicStreamSequencer::MarkConsumed(size_t num_bytes_consumed) { |
| 203 size_t end_offset = num_bytes_consumed_ + num_bytes_consumed; |
| 204 while (!frames_.empty()) { |
| 205 FrameMap::iterator it = frames_.begin(); |
| 206 if (it->first + it->second.length() <= end_offset) { |
| 207 // This chunk is entirely consumed. |
| 208 frames_.erase(it); |
| 209 continue; |
| 210 } |
| 211 |
| 212 if (it->first != end_offset) { |
| 213 // Partially consume this frame. |
| 214 frames_.insert(make_pair(end_offset, |
| 215 it->second.substr(end_offset - it->first))); |
| 216 frames_.erase(it); |
| 217 } |
| 218 break; |
| 219 } |
| 220 num_bytes_consumed_ = end_offset; |
| 221 } |
| 222 |
| 142 bool QuicStreamSequencer::HasBytesToRead() const { | 223 bool QuicStreamSequencer::HasBytesToRead() const { |
| 143 FrameMap::const_iterator it = frames_.begin(); | 224 FrameMap::const_iterator it = frames_.begin(); |
| 144 | 225 |
| 145 return it != frames_.end() && it->first == num_bytes_consumed_; | 226 return it != frames_.end() && it->first == num_bytes_consumed_; |
| 146 } | 227 } |
| 147 | 228 |
| 148 bool QuicStreamSequencer::IsHalfClosed() const { | 229 bool QuicStreamSequencer::IsHalfClosed() const { |
| 149 return num_bytes_consumed_ >= close_offset_; | 230 return num_bytes_consumed_ >= close_offset_; |
| 150 } | 231 } |
| 151 | 232 |
| 152 bool QuicStreamSequencer::IsClosed() const { | 233 bool QuicStreamSequencer::IsClosed() const { |
| 153 return num_bytes_consumed_ >= close_offset_ && half_close_ == false; | 234 return num_bytes_consumed_ >= close_offset_ && half_close_ == false; |
| 154 } | 235 } |
| 155 | 236 |
| 156 bool QuicStreamSequencer::IsDuplicate(const QuicStreamFrame& frame) const { | 237 bool QuicStreamSequencer::IsDuplicate(const QuicStreamFrame& frame) const { |
| 157 // A frame is duplicate if the frame offset is smaller than our bytes consumed | 238 // A frame is duplicate if the frame offset is smaller than our bytes consumed |
| 158 // or we have stored the frame in our map. | 239 // or we have stored the frame in our map. |
| 159 // TODO(pwestin): Is it possible that a new frame contain more data even if | 240 // TODO(pwestin): Is it possible that a new frame contain more data even if |
| 160 // the offset is the same? | 241 // the offset is the same? |
| 161 return frame.offset < num_bytes_consumed_ || | 242 return frame.offset < num_bytes_consumed_ || |
| 162 frames_.find(frame.offset) != frames_.end(); | 243 frames_.find(frame.offset) != frames_.end(); |
| 163 } | 244 } |
| 164 | 245 |
| 165 void QuicStreamSequencer::FlushBufferedFrames() { | 246 void QuicStreamSequencer::FlushBufferedFrames() { |
| 166 FrameMap::iterator it = frames_.find(num_bytes_consumed_); | 247 FrameMap::iterator it = frames_.find(num_bytes_consumed_); |
| 167 while (it != frames_.end()) { | 248 while (it != frames_.end()) { |
| 168 DVLOG(1) << "Flushing buffered packet at offset " << it->first; | 249 DVLOG(1) << "Flushing buffered packet at offset " << it->first; |
| 169 string* data = &it->second; | 250 string* data = &it->second; |
| 170 size_t bytes_consumed = stream_->ProcessData(data->c_str(), data->size()); | 251 size_t bytes_consumed = stream_->ProcessRawData(data->c_str(), |
| 252 data->size()); |
| 171 num_bytes_consumed_ += bytes_consumed; | 253 num_bytes_consumed_ += bytes_consumed; |
| 172 if (MaybeCloseStream()) { | 254 if (MaybeCloseStream()) { |
| 173 return; | 255 return; |
| 174 } | 256 } |
| 175 if (bytes_consumed > data->size()) { | 257 if (bytes_consumed > data->size()) { |
| 176 stream_->Close(QUIC_SERVER_ERROR_PROCESSING_STREAM); // Programming error | 258 stream_->Close(QUIC_SERVER_ERROR_PROCESSING_STREAM); // Programming error |
| 177 return; | 259 return; |
| 178 } else if (bytes_consumed == data->size()) { | 260 } else if (bytes_consumed == data->size()) { |
| 179 frames_.erase(it); | 261 frames_.erase(it); |
| 180 it = frames_.find(num_bytes_consumed_); | 262 it = frames_.find(num_bytes_consumed_); |
| 181 } else { | 263 } else { |
| 182 string new_data = it->second.substr(bytes_consumed); | 264 string new_data = it->second.substr(bytes_consumed); |
| 183 frames_.erase(it); | 265 frames_.erase(it); |
| 184 frames_.insert(make_pair(num_bytes_consumed_, new_data)); | 266 frames_.insert(make_pair(num_bytes_consumed_, new_data)); |
| 185 return; | 267 return; |
| 186 } | 268 } |
| 187 } | 269 } |
| 188 } | 270 } |
| 189 | 271 |
| 190 } // namespace net | 272 } // namespace net |
| OLD | NEW |