chunked_upload_data_stream.cc 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "net/base/chunked_upload_data_stream.h"
  5. #include "base/check_op.h"
  6. #include "base/memory/ptr_util.h"
  7. #include "net/base/io_buffer.h"
  8. #include "net/base/net_errors.h"
  9. namespace net {
  10. ChunkedUploadDataStream::Writer::~Writer() = default;
  11. bool ChunkedUploadDataStream::Writer::AppendData(const char* data,
  12. int data_len,
  13. bool is_done) {
  14. if (!upload_data_stream_)
  15. return false;
  16. upload_data_stream_->AppendData(data, data_len, is_done);
  17. return true;
  18. }
  19. ChunkedUploadDataStream::Writer::Writer(
  20. base::WeakPtr<ChunkedUploadDataStream> upload_data_stream)
  21. : upload_data_stream_(upload_data_stream) {}
  22. ChunkedUploadDataStream::ChunkedUploadDataStream(int64_t identifier,
  23. bool has_null_source)
  24. : UploadDataStream(/*is_chunked=*/true, has_null_source, identifier) {}
  25. ChunkedUploadDataStream::~ChunkedUploadDataStream() = default;
  26. std::unique_ptr<ChunkedUploadDataStream::Writer>
  27. ChunkedUploadDataStream::CreateWriter() {
  28. return base::WrapUnique(new Writer(weak_factory_.GetWeakPtr()));
  29. }
  30. void ChunkedUploadDataStream::AppendData(
  31. const char* data, int data_len, bool is_done) {
  32. DCHECK(!all_data_appended_);
  33. DCHECK(data_len > 0 || is_done);
  34. if (data_len > 0) {
  35. DCHECK(data);
  36. upload_data_.push_back(
  37. std::make_unique<std::vector<char>>(data, data + data_len));
  38. }
  39. all_data_appended_ = is_done;
  40. if (!read_buffer_.get())
  41. return;
  42. int result = ReadChunk(read_buffer_.get(), read_buffer_len_);
  43. // Shouldn't get an error or ERR_IO_PENDING.
  44. DCHECK_GE(result, 0);
  45. read_buffer_ = nullptr;
  46. read_buffer_len_ = 0;
  47. OnReadCompleted(result);
  48. }
  49. int ChunkedUploadDataStream::InitInternal(const NetLogWithSource& net_log) {
  50. // ResetInternal should already have been called.
  51. DCHECK(!read_buffer_.get());
  52. DCHECK_EQ(0u, read_index_);
  53. DCHECK_EQ(0u, read_offset_);
  54. return OK;
  55. }
  56. int ChunkedUploadDataStream::ReadInternal(IOBuffer* buf, int buf_len) {
  57. DCHECK_LT(0, buf_len);
  58. DCHECK(!read_buffer_.get());
  59. int result = ReadChunk(buf, buf_len);
  60. if (result == ERR_IO_PENDING) {
  61. read_buffer_ = buf;
  62. read_buffer_len_ = buf_len;
  63. }
  64. return result;
  65. }
  66. void ChunkedUploadDataStream::ResetInternal() {
  67. read_buffer_ = nullptr;
  68. read_buffer_len_ = 0;
  69. read_index_ = 0;
  70. read_offset_ = 0;
  71. }
  72. int ChunkedUploadDataStream::ReadChunk(IOBuffer* buf, int buf_len) {
  73. // Copy as much data as possible from |upload_data_| to |buf|.
  74. int bytes_read = 0;
  75. while (read_index_ < upload_data_.size() && bytes_read < buf_len) {
  76. std::vector<char>* data = upload_data_[read_index_].get();
  77. size_t bytes_to_read =
  78. std::min(static_cast<size_t>(buf_len - bytes_read),
  79. data->size() - read_offset_);
  80. memcpy(buf->data() + bytes_read, data->data() + read_offset_,
  81. bytes_to_read);
  82. bytes_read += bytes_to_read;
  83. read_offset_ += bytes_to_read;
  84. if (read_offset_ == data->size()) {
  85. read_index_++;
  86. read_offset_ = 0;
  87. }
  88. }
  89. DCHECK_LE(bytes_read, buf_len);
  90. // If no data was written, and not all data has been appended, return
  91. // ERR_IO_PENDING. The read will be completed in the next call to AppendData.
  92. if (bytes_read == 0 && !all_data_appended_)
  93. return ERR_IO_PENDING;
  94. if (read_index_ == upload_data_.size() && all_data_appended_)
  95. SetIsFinalChunk();
  96. return bytes_read;
  97. }
  98. } // namespace net