mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-12-01 01:36:09 +03:00
157 lines
4.4 KiB
C++
157 lines
4.4 KiB
C++
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
// found in the LICENSE file.
|
||
|
|
||
|
#include "net/base/elements_upload_data_stream.h"
|
||
|
|
||
|
#include "base/bind.h"
|
||
|
#include "base/logging.h"
|
||
|
#include "net/base/completion_callback.h"
|
||
|
#include "net/base/io_buffer.h"
|
||
|
#include "net/base/net_errors.h"
|
||
|
#include "net/base/upload_bytes_element_reader.h"
|
||
|
#include "net/base/upload_element_reader.h"
|
||
|
|
||
|
namespace net {
|
||
|
|
||
|
ElementsUploadDataStream::ElementsUploadDataStream(
|
||
|
std::vector<std::unique_ptr<UploadElementReader>> element_readers,
|
||
|
int64_t identifier)
|
||
|
: UploadDataStream(false, identifier),
|
||
|
element_readers_(std::move(element_readers)),
|
||
|
element_index_(0),
|
||
|
read_error_(OK),
|
||
|
weak_ptr_factory_(this) {}
|
||
|
|
||
|
ElementsUploadDataStream::~ElementsUploadDataStream() = default;
|
||
|
|
||
|
std::unique_ptr<UploadDataStream> ElementsUploadDataStream::CreateWithReader(
|
||
|
std::unique_ptr<UploadElementReader> reader,
|
||
|
int64_t identifier) {
|
||
|
std::vector<std::unique_ptr<UploadElementReader>> readers;
|
||
|
readers.push_back(std::move(reader));
|
||
|
return std::unique_ptr<UploadDataStream>(
|
||
|
new ElementsUploadDataStream(std::move(readers), identifier));
|
||
|
}
|
||
|
|
||
|
int ElementsUploadDataStream::InitInternal(const NetLogWithSource& net_log) {
|
||
|
return InitElements(0);
|
||
|
}
|
||
|
|
||
|
int ElementsUploadDataStream::ReadInternal(
|
||
|
IOBuffer* buf,
|
||
|
int buf_len) {
|
||
|
DCHECK_GT(buf_len, 0);
|
||
|
return ReadElements(new DrainableIOBuffer(buf, buf_len));
|
||
|
}
|
||
|
|
||
|
bool ElementsUploadDataStream::IsInMemory() const {
|
||
|
for (const std::unique_ptr<UploadElementReader>& it : element_readers_) {
|
||
|
if (!it->IsInMemory())
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
const std::vector<std::unique_ptr<UploadElementReader>>*
|
||
|
ElementsUploadDataStream::GetElementReaders() const {
|
||
|
return &element_readers_;
|
||
|
}
|
||
|
|
||
|
void ElementsUploadDataStream::ResetInternal() {
|
||
|
weak_ptr_factory_.InvalidateWeakPtrs();
|
||
|
read_error_ = OK;
|
||
|
element_index_ = 0;
|
||
|
}
|
||
|
|
||
|
int ElementsUploadDataStream::InitElements(size_t start_index) {
|
||
|
// Call Init() for all elements.
|
||
|
for (size_t i = start_index; i < element_readers_.size(); ++i) {
|
||
|
UploadElementReader* reader = element_readers_[i].get();
|
||
|
// When new_result is ERR_IO_PENDING, InitInternal() will be called
|
||
|
// with start_index == i + 1 when reader->Init() finishes.
|
||
|
int result = reader->Init(
|
||
|
base::Bind(&ElementsUploadDataStream::OnInitElementCompleted,
|
||
|
weak_ptr_factory_.GetWeakPtr(),
|
||
|
i));
|
||
|
DCHECK(result != ERR_IO_PENDING || !reader->IsInMemory());
|
||
|
DCHECK_LE(result, OK);
|
||
|
if (result != OK)
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
uint64_t total_size = 0;
|
||
|
for (const std::unique_ptr<UploadElementReader>& it : element_readers_) {
|
||
|
total_size += it->GetContentLength();
|
||
|
}
|
||
|
SetSize(total_size);
|
||
|
return OK;
|
||
|
}
|
||
|
|
||
|
void ElementsUploadDataStream::OnInitElementCompleted(size_t index,
|
||
|
int result) {
|
||
|
DCHECK_NE(ERR_IO_PENDING, result);
|
||
|
|
||
|
// Check the last result.
|
||
|
if (result == OK)
|
||
|
result = InitElements(index + 1);
|
||
|
|
||
|
if (result != ERR_IO_PENDING)
|
||
|
OnInitCompleted(result);
|
||
|
}
|
||
|
|
||
|
int ElementsUploadDataStream::ReadElements(
|
||
|
const scoped_refptr<DrainableIOBuffer>& buf) {
|
||
|
while (read_error_ == OK && element_index_ < element_readers_.size()) {
|
||
|
UploadElementReader* reader = element_readers_[element_index_].get();
|
||
|
|
||
|
if (reader->BytesRemaining() == 0) {
|
||
|
++element_index_;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (buf->BytesRemaining() == 0)
|
||
|
break;
|
||
|
|
||
|
int result = reader->Read(
|
||
|
buf.get(),
|
||
|
buf->BytesRemaining(),
|
||
|
base::Bind(&ElementsUploadDataStream::OnReadElementCompleted,
|
||
|
weak_ptr_factory_.GetWeakPtr(),
|
||
|
buf));
|
||
|
if (result == ERR_IO_PENDING)
|
||
|
return ERR_IO_PENDING;
|
||
|
ProcessReadResult(buf, result);
|
||
|
}
|
||
|
|
||
|
if (buf->BytesConsumed() > 0)
|
||
|
return buf->BytesConsumed();
|
||
|
|
||
|
return read_error_;
|
||
|
}
|
||
|
|
||
|
void ElementsUploadDataStream::OnReadElementCompleted(
|
||
|
const scoped_refptr<DrainableIOBuffer>& buf,
|
||
|
int result) {
|
||
|
ProcessReadResult(buf, result);
|
||
|
|
||
|
result = ReadElements(buf);
|
||
|
if (result != ERR_IO_PENDING)
|
||
|
OnReadCompleted(result);
|
||
|
}
|
||
|
|
||
|
void ElementsUploadDataStream::ProcessReadResult(
|
||
|
const scoped_refptr<DrainableIOBuffer>& buf,
|
||
|
int result) {
|
||
|
DCHECK_NE(ERR_IO_PENDING, result);
|
||
|
DCHECK(!read_error_);
|
||
|
|
||
|
if (result >= 0) {
|
||
|
buf->DidConsume(result);
|
||
|
} else {
|
||
|
read_error_ = result;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} // namespace net
|