| 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 |