OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/websockets/websocket_deflate_stream.h" | 5 #include "net/websockets/websocket_deflate_stream.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 (*frames)[i] = NULL; | 125 (*frames)[i] = NULL; |
126 predictor_->RecordInputDataFrame(frame.get()); | 126 predictor_->RecordInputDataFrame(frame.get()); |
127 | 127 |
128 if (writing_state_ == WRITING_UNCOMPRESSED_MESSAGE) { | 128 if (writing_state_ == WRITING_UNCOMPRESSED_MESSAGE) { |
129 if (frame->header.final) | 129 if (frame->header.final) |
130 writing_state_ = NOT_WRITING; | 130 writing_state_ = NOT_WRITING; |
131 predictor_->RecordWrittenDataFrame(frame.get()); | 131 predictor_->RecordWrittenDataFrame(frame.get()); |
132 frames_to_write.push_back(frame.release()); | 132 frames_to_write.push_back(frame.release()); |
133 current_writing_opcode_ = WebSocketFrameHeader::kOpCodeContinuation; | 133 current_writing_opcode_ = WebSocketFrameHeader::kOpCodeContinuation; |
134 } else { | 134 } else { |
135 if (frame->data && !deflater_.AddBytes(frame->data->data(), | 135 if (frame->data.get() && |
136 frame->header.payload_length)) { | 136 !deflater_.AddBytes(frame->data->data(), |
| 137 frame->header.payload_length)) { |
137 DVLOG(1) << "WebSocket protocol error. " | 138 DVLOG(1) << "WebSocket protocol error. " |
138 << "deflater_.AddBytes() returns an error."; | 139 << "deflater_.AddBytes() returns an error."; |
139 return ERR_WS_PROTOCOL_ERROR; | 140 return ERR_WS_PROTOCOL_ERROR; |
140 } | 141 } |
141 if (frame->header.final && !deflater_.Finish()) { | 142 if (frame->header.final && !deflater_.Finish()) { |
142 DVLOG(1) << "WebSocket protocol error. " | 143 DVLOG(1) << "WebSocket protocol error. " |
143 << "deflater_.Finish() returns an error."; | 144 << "deflater_.Finish() returns an error."; |
144 return ERR_WS_PROTOCOL_ERROR; | 145 return ERR_WS_PROTOCOL_ERROR; |
145 } | 146 } |
146 | 147 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 } | 196 } |
196 NOTREACHED(); | 197 NOTREACHED(); |
197 } | 198 } |
198 | 199 |
199 int WebSocketDeflateStream::AppendCompressedFrame( | 200 int WebSocketDeflateStream::AppendCompressedFrame( |
200 const WebSocketFrameHeader& header, | 201 const WebSocketFrameHeader& header, |
201 ScopedVector<WebSocketFrame>* frames_to_write) { | 202 ScopedVector<WebSocketFrame>* frames_to_write) { |
202 const WebSocketFrameHeader::OpCode opcode = current_writing_opcode_; | 203 const WebSocketFrameHeader::OpCode opcode = current_writing_opcode_; |
203 scoped_refptr<IOBufferWithSize> compressed_payload = | 204 scoped_refptr<IOBufferWithSize> compressed_payload = |
204 deflater_.GetOutput(deflater_.CurrentOutputSize()); | 205 deflater_.GetOutput(deflater_.CurrentOutputSize()); |
205 if (!compressed_payload) { | 206 if (!compressed_payload.get()) { |
206 DVLOG(1) << "WebSocket protocol error. " | 207 DVLOG(1) << "WebSocket protocol error. " |
207 << "deflater_.GetOutput() returns an error."; | 208 << "deflater_.GetOutput() returns an error."; |
208 return ERR_WS_PROTOCOL_ERROR; | 209 return ERR_WS_PROTOCOL_ERROR; |
209 } | 210 } |
210 scoped_ptr<WebSocketFrame> compressed(new WebSocketFrame(opcode)); | 211 scoped_ptr<WebSocketFrame> compressed(new WebSocketFrame(opcode)); |
211 compressed->header.CopyFrom(header); | 212 compressed->header.CopyFrom(header); |
212 compressed->header.opcode = opcode; | 213 compressed->header.opcode = opcode; |
213 compressed->header.final = header.final; | 214 compressed->header.final = header.final; |
214 compressed->header.reserved1 = | 215 compressed->header.reserved1 = |
215 (opcode != WebSocketFrameHeader::kOpCodeContinuation); | 216 (opcode != WebSocketFrameHeader::kOpCodeContinuation); |
216 compressed->data = compressed_payload; | 217 compressed->data = compressed_payload; |
217 compressed->header.payload_length = compressed_payload->size(); | 218 compressed->header.payload_length = compressed_payload->size(); |
218 | 219 |
219 current_writing_opcode_ = WebSocketFrameHeader::kOpCodeContinuation; | 220 current_writing_opcode_ = WebSocketFrameHeader::kOpCodeContinuation; |
220 predictor_->RecordWrittenDataFrame(compressed.get()); | 221 predictor_->RecordWrittenDataFrame(compressed.get()); |
221 frames_to_write->push_back(compressed.release()); | 222 frames_to_write->push_back(compressed.release()); |
222 return OK; | 223 return OK; |
223 } | 224 } |
224 | 225 |
225 int WebSocketDeflateStream::AppendPossiblyCompressedMessage( | 226 int WebSocketDeflateStream::AppendPossiblyCompressedMessage( |
226 ScopedVector<WebSocketFrame>* frames, | 227 ScopedVector<WebSocketFrame>* frames, |
227 ScopedVector<WebSocketFrame>* frames_to_write) { | 228 ScopedVector<WebSocketFrame>* frames_to_write) { |
228 DCHECK(!frames->empty()); | 229 DCHECK(!frames->empty()); |
229 | 230 |
230 const WebSocketFrameHeader::OpCode opcode = current_writing_opcode_; | 231 const WebSocketFrameHeader::OpCode opcode = current_writing_opcode_; |
231 scoped_refptr<IOBufferWithSize> compressed_payload = | 232 scoped_refptr<IOBufferWithSize> compressed_payload = |
232 deflater_.GetOutput(deflater_.CurrentOutputSize()); | 233 deflater_.GetOutput(deflater_.CurrentOutputSize()); |
233 if (!compressed_payload) { | 234 if (!compressed_payload.get()) { |
234 DVLOG(1) << "WebSocket protocol error. " | 235 DVLOG(1) << "WebSocket protocol error. " |
235 << "deflater_.GetOutput() returns an error."; | 236 << "deflater_.GetOutput() returns an error."; |
236 return ERR_WS_PROTOCOL_ERROR; | 237 return ERR_WS_PROTOCOL_ERROR; |
237 } | 238 } |
238 | 239 |
239 uint64 original_payload_length = 0; | 240 uint64 original_payload_length = 0; |
240 for (size_t i = 0; i < frames->size(); ++i) { | 241 for (size_t i = 0; i < frames->size(); ++i) { |
241 WebSocketFrame* frame = (*frames)[i]; | 242 WebSocketFrame* frame = (*frames)[i]; |
242 // Asserts checking that frames represent one whole data message. | 243 // Asserts checking that frames represent one whole data message. |
243 DCHECK(WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode)); | 244 DCHECK(WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode)); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 } | 304 } |
304 } | 305 } |
305 | 306 |
306 if (reading_state_ == READING_UNCOMPRESSED_MESSAGE) { | 307 if (reading_state_ == READING_UNCOMPRESSED_MESSAGE) { |
307 if (frame->header.final) | 308 if (frame->header.final) |
308 reading_state_ = NOT_READING; | 309 reading_state_ = NOT_READING; |
309 current_reading_opcode_ = WebSocketFrameHeader::kOpCodeContinuation; | 310 current_reading_opcode_ = WebSocketFrameHeader::kOpCodeContinuation; |
310 frames_to_output.push_back(frame.release()); | 311 frames_to_output.push_back(frame.release()); |
311 } else { | 312 } else { |
312 DCHECK_EQ(reading_state_, READING_COMPRESSED_MESSAGE); | 313 DCHECK_EQ(reading_state_, READING_COMPRESSED_MESSAGE); |
313 if (frame->data && !inflater_.AddBytes(frame->data->data(), | 314 if (frame->data.get() && |
314 frame->header.payload_length)) { | 315 !inflater_.AddBytes(frame->data->data(), |
| 316 frame->header.payload_length)) { |
315 DVLOG(1) << "WebSocket protocol error. " | 317 DVLOG(1) << "WebSocket protocol error. " |
316 << "inflater_.AddBytes() returns an error."; | 318 << "inflater_.AddBytes() returns an error."; |
317 return ERR_WS_PROTOCOL_ERROR; | 319 return ERR_WS_PROTOCOL_ERROR; |
318 } | 320 } |
319 if (frame->header.final) { | 321 if (frame->header.final) { |
320 if (!inflater_.Finish()) { | 322 if (!inflater_.Finish()) { |
321 DVLOG(1) << "WebSocket protocol error. " | 323 DVLOG(1) << "WebSocket protocol error. " |
322 << "inflater_.Finish() returns an error."; | 324 << "inflater_.Finish() returns an error."; |
323 return ERR_WS_PROTOCOL_ERROR; | 325 return ERR_WS_PROTOCOL_ERROR; |
324 } | 326 } |
325 } | 327 } |
326 // TODO(yhirano): Many frames can be generated by the inflater and | 328 // TODO(yhirano): Many frames can be generated by the inflater and |
327 // memory consumption can grow. | 329 // memory consumption can grow. |
328 // We could avoid it, but avoiding it makes this class much more | 330 // We could avoid it, but avoiding it makes this class much more |
329 // complicated. | 331 // complicated. |
330 while (inflater_.CurrentOutputSize() >= kChunkSize || | 332 while (inflater_.CurrentOutputSize() >= kChunkSize || |
331 frame->header.final) { | 333 frame->header.final) { |
332 size_t size = std::min(kChunkSize, inflater_.CurrentOutputSize()); | 334 size_t size = std::min(kChunkSize, inflater_.CurrentOutputSize()); |
333 scoped_ptr<WebSocketFrame> inflated( | 335 scoped_ptr<WebSocketFrame> inflated( |
334 new WebSocketFrame(WebSocketFrameHeader::kOpCodeText)); | 336 new WebSocketFrame(WebSocketFrameHeader::kOpCodeText)); |
335 scoped_refptr<IOBufferWithSize> data = inflater_.GetOutput(size); | 337 scoped_refptr<IOBufferWithSize> data = inflater_.GetOutput(size); |
336 bool is_final = !inflater_.CurrentOutputSize() && frame->header.final; | 338 bool is_final = !inflater_.CurrentOutputSize() && frame->header.final; |
337 if (!data) { | 339 if (!data.get()) { |
338 DVLOG(1) << "WebSocket protocol error. " | 340 DVLOG(1) << "WebSocket protocol error. " |
339 << "inflater_.GetOutput() returns an error."; | 341 << "inflater_.GetOutput() returns an error."; |
340 return ERR_WS_PROTOCOL_ERROR; | 342 return ERR_WS_PROTOCOL_ERROR; |
341 } | 343 } |
342 inflated->header.CopyFrom(frame->header); | 344 inflated->header.CopyFrom(frame->header); |
343 inflated->header.opcode = current_reading_opcode_; | 345 inflated->header.opcode = current_reading_opcode_; |
344 inflated->header.final = is_final; | 346 inflated->header.final = is_final; |
345 inflated->header.reserved1 = false; | 347 inflated->header.reserved1 = false; |
346 inflated->data = data; | 348 inflated->data = data; |
347 inflated->header.payload_length = data->size(); | 349 inflated->header.payload_length = data->size(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 DCHECK(!frames->empty()); | 383 DCHECK(!frames->empty()); |
382 | 384 |
383 result = Inflate(frames); | 385 result = Inflate(frames); |
384 } | 386 } |
385 if (result < 0) | 387 if (result < 0) |
386 frames->clear(); | 388 frames->clear(); |
387 return result; | 389 return result; |
388 } | 390 } |
389 | 391 |
390 } // namespace net | 392 } // namespace net |
OLD | NEW |