diff --git a/net/net.gypi b/net/net.gypi index b7b1a02dbdf221..dfa7cafd2003f7 100644 --- a/net/net.gypi +++ b/net/net.gypi @@ -992,8 +992,6 @@ 'quic/core/crypto/strike_register_client.h', 'quic/core/interval.h', 'quic/core/interval_set.h', - 'quic/core/iovector.cc', - 'quic/core/iovector.h', 'quic/core/quic_address_mismatch.cc', 'quic/core/quic_address_mismatch.h', 'quic/core/quic_alarm.cc', @@ -1714,7 +1712,6 @@ 'quic/core/crypto/strike_register_test.cc', 'quic/core/interval_set_test.cc', 'quic/core/interval_test.cc', - 'quic/core/iovector_test.cc', 'quic/core/quic_address_mismatch_test.cc', 'quic/core/quic_alarm_test.cc', 'quic/core/quic_arena_scoped_ptr_test.cc', diff --git a/net/quic/core/iovector.cc b/net/quic/core/iovector.cc deleted file mode 100644 index d7c919c9475f85..00000000000000 --- a/net/quic/core/iovector.cc +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2013 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/quic/core/iovector.h" - -namespace net { - -IOVector::IOVector() {} - -IOVector::IOVector(const IOVector& other) = default; - -IOVector::~IOVector() {} - -} // namespace net diff --git a/net/quic/core/iovector.h b/net/quic/core/iovector.h deleted file mode 100644 index cf77a9acc26af7..00000000000000 --- a/net/quic/core/iovector.h +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright 2013 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. - -#ifndef NET_QUIC_IOVECTOR_H_ -#define NET_QUIC_IOVECTOR_H_ - -#include - -#include -#include - -#include "base/logging.h" -#include "net/base/iovec.h" -#include "net/base/net_export.h" - -namespace net { - -// Calculate the total number of bytes in an array of iovec structures. -inline size_t TotalIovecLength(const struct iovec* iov, size_t iovcnt) { - size_t length = 0; - if (iov != NULL) { - for (size_t i = 0; i < iovcnt; ++i) { - length += iov[i].iov_len; - } - } - return length; -} - -// IOVector is a helper class that makes it easier to work with POSIX vector I/O -// struct. It is a thin wrapper by design and thus has no virtual functions and -// all inlined methods. This class makes no assumptions about the ordering of -// the pointer values of the blocks appended, it simply counts bytes when asked -// to consume bytes. -// -// IOVector is a bookkeeping object that collects a description of buffers to -// be read or written together and in order. It does not take ownership of the -// blocks appended. -// -// Because it is used for scatter-gather operations, the order in which the -// buffer blocks are added to the IOVector is important to the client. The -// intended usage pattern is: -// -// iovector.Append(p0, len0); -// ... -// iovector.Append(pn, lenn); -// int bytes_written = writev(fd, iovector.iovec(), iovector.Size()); -// if (bytes_written > 0) -// iovector.Consume(bytes_written); -// -// The sequence is the same for readv, except that Consume() in this case is -// used to change the IOVector to only keep track of description of blocks of -// memory not yet written to. -// -// IOVector does not have any method to change the iovec entries that it -// accumulates. This is due to the block merging nature of Append(): we'd like -// to avoid accidentally change an entry that is assembled by two or more -// Append()'s by simply an index access. -// -class NET_EXPORT_PRIVATE IOVector { - public: - // Provide a default constructor so it'll never be inhibited by adding other - // constructors. - IOVector(); - IOVector(const IOVector& other); - ~IOVector(); - - // Provides a way to convert system call-like iovec representation to - // IOVector. - void AppendIovec(const struct iovec* iov, size_t iovcnt) { - for (size_t i = 0; i < iovcnt; ++i) - Append(static_cast(iov[i].iov_base), iov[i].iov_len); - } - - // Appends at most max_bytes from iovec to the IOVector. - size_t AppendIovecAtMostBytes(const struct iovec* iov, - size_t iovcnt, - size_t max_bytes) { - size_t bytes_appended = 0; - for (size_t i = 0; i < iovcnt && max_bytes > 0; ++i) { - const size_t length = std::min(max_bytes, iov[i].iov_len); - Append(static_cast(iov[i].iov_base), length); - max_bytes -= length; - bytes_appended += length; - } - return bytes_appended; - } - - // Append another block to the IOVector. Since IOVector can be used for read - // and write, it always takes char*. Clients that writes will need to cast - // away the constant of the pointer before appending a block. - void Append(char* buffer, size_t length) { - if (buffer != nullptr && length > 0) { - if (iovec_.size() > 0) { - struct iovec& last = iovec_.back(); - // If the new block is contiguous with the last block, just extend. - if (static_cast(last.iov_base) + last.iov_len == buffer) { - last.iov_len += length; - return; - } - } - struct iovec tmp = {buffer, length}; - iovec_.push_back(tmp); - } - } - - // Same as Append, but doesn't do the tail merge optimization. - // Intended for testing. - void AppendNoCoalesce(char* buffer, size_t length) { - if (buffer != nullptr && length > 0) { - struct iovec tmp = {buffer, length}; - iovec_.push_back(tmp); - } - } - - // Remove a number of bytes from the beginning of the IOVector. Since vector - // I/O operations always occur at the beginning of the block list, a method - // to remove bytes at the end is not provided. - // It returns the number of bytes actually consumed (it'll only be smaller - // than the requested number if the IOVector contains less data). - size_t Consume(size_t length) { - if (length == 0) - return 0; - - size_t bytes_to_consume = length; - std::vector::iterator iter = iovec_.begin(); - std::vector::iterator end = iovec_.end(); - for (; iter < end && bytes_to_consume >= iter->iov_len; ++iter) { - bytes_to_consume -= iter->iov_len; - } - iovec_.erase(iovec_.begin(), iter); - if (!iovec_.empty() && bytes_to_consume != 0) { - iovec_[0].iov_base = - static_cast(iovec_[0].iov_base) + bytes_to_consume; - iovec_[0].iov_len -= bytes_to_consume; - return length; - } - if (iovec_.size() == 0 && bytes_to_consume > 0) { - LOG(DFATAL) << "Attempting to consume " << bytes_to_consume - << " non-existent bytes."; - } - // At this point bytes_to_consume is the number of wanted bytes left over - // after walking through all the iovec entries. - return length - bytes_to_consume; - } - - // Identical to Consume, but also copies the portion of the buffer being - // consumed into |buffer|. |buffer| must be at least size |length|. If - // the IOVector is less than |length|, the method consumes the entire - // IOVector, logs an error and returns the length consumed. - size_t ConsumeAndCopy(size_t length, char* buffer) { - if (length == 0) - return 0; - - size_t bytes_to_consume = length; - // First consume all the iovecs which can be consumed completely. - std::vector::iterator iter = iovec_.begin(); - std::vector::iterator end = iovec_.end(); - for (; iter < end && bytes_to_consume >= iter->iov_len; ++iter) { - memcpy(buffer, iter->iov_base, iter->iov_len); - bytes_to_consume -= iter->iov_len; - buffer += iter->iov_len; - } - iovec_.erase(iovec_.begin(), iter); - if (bytes_to_consume == 0) { - return length; - } - if (iovec_.empty()) { - LOG_IF(DFATAL, bytes_to_consume > 0) << "Attempting to consume " - << bytes_to_consume - << " non-existent bytes."; - return length - bytes_to_consume; - } - // Partially consume the next iovec. - memcpy(buffer, iovec_[0].iov_base, bytes_to_consume); - iovec_[0].iov_base = - static_cast(iovec_[0].iov_base) + bytes_to_consume; - iovec_[0].iov_len -= bytes_to_consume; - return length; - } - - // TODO(joechan): If capacity is large, swap out for a blank one. - // Clears the IOVector object to contain no blocks. - void Clear() { iovec_.clear(); } - - // Swap the guts of two IOVector. - void Swap(IOVector* other) { iovec_.swap(other->iovec_); } - - // Returns the number of valid blocks in the IOVector (not the number of - // bytes). - size_t Size() const { return iovec_.size(); } - - // Returns the total storage used by the IOVector in number of blocks (not - // the number of bytes). - size_t Capacity() const { return iovec_.capacity(); } - - // Returns true if there are no blocks in the IOVector. - bool Empty() const { return iovec_.empty(); } - - // Returns the pointer to the beginning of the iovec to be used for vector - // I/O operations. If the IOVector has no blocks appened, this function - // returns NULL. - struct iovec* iovec() { - return !Empty() ? &iovec_[0] : NULL; - } - - // Const version. - const struct iovec* iovec() const { return !Empty() ? &iovec_[0] : NULL; } - - // Returns a pointer to one past the last byte of the last block. If the - // IOVector is empty, NULL is returned. - const char* LastBlockEnd() const { - return iovec_.size() > 0 - ? static_cast(iovec_.back().iov_base) + - iovec_.back().iov_len - : NULL; - } - - // Returns the total number of bytes in the IOVector. - size_t TotalBufferSize() const { return TotalIovecLength(iovec(), Size()); } - - void Resize(size_t count) { iovec_.resize(count); } - - private: - std::vector iovec_; - - // IOVector has value-semantics; copy and assignment are allowed. - // This class does not explicitly define copy/move constructors or the - // assignment operator to preserve compiler-generated copy/move constructors - // and assignment operators. Note that since IOVector does not own the - // actual buffers that the struct iovecs point to, copies and assignments - // result in a shallow copy of the buffers; resulting IOVectors will point - // to the same copy of the underlying data. -}; - -} // namespace net - -#endif // NET_QUIC_IOVECTOR_H_ diff --git a/net/quic/core/iovector_test.cc b/net/quic/core/iovector_test.cc deleted file mode 100644 index 06b40bdf9a0677..00000000000000 --- a/net/quic/core/iovector_test.cc +++ /dev/null @@ -1,373 +0,0 @@ -// Copyright 2013 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/quic/core/iovector.h" - -#include - -#include -#include - -#include "net/test/gtest_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -using std::string; - -namespace net { -namespace test { -namespace { - -const char* const test_data[] = { - "test string 1, a medium size one.", "test string2", - "test string 3, a looooooooooooong loooooooooooooooong string"}; - -TEST(IOVectorTest, CopyConstructor) { - IOVector iov1; - for (size_t i = 0; i < arraysize(test_data); ++i) { - iov1.Append(const_cast(test_data[i]), strlen(test_data[i])); - } - IOVector iov2 = iov1; - EXPECT_EQ(iov2.Size(), iov1.Size()); - for (size_t i = 0; i < iov2.Size(); ++i) { - EXPECT_TRUE(iov2.iovec()[i].iov_base == iov1.iovec()[i].iov_base); - EXPECT_EQ(iov2.iovec()[i].iov_len, iov1.iovec()[i].iov_len); - } - EXPECT_EQ(iov2.TotalBufferSize(), iov1.TotalBufferSize()); -} - -TEST(IOVectorTest, AssignmentOperator) { - IOVector iov1; - for (size_t i = 0; i < arraysize(test_data); ++i) { - iov1.Append(const_cast(test_data[i]), strlen(test_data[i])); - } - IOVector iov2; - iov2.Append(const_cast("ephemeral string"), 16); - // The following assignment results in a shallow copy; - // both IOVectors point to the same underlying data. - iov2 = iov1; - EXPECT_EQ(iov2.Size(), iov1.Size()); - for (size_t i = 0; i < iov2.Size(); ++i) { - EXPECT_TRUE(iov2.iovec()[i].iov_base == iov1.iovec()[i].iov_base); - EXPECT_EQ(iov2.iovec()[i].iov_len, iov1.iovec()[i].iov_len); - } - EXPECT_EQ(iov2.TotalBufferSize(), iov1.TotalBufferSize()); -} - -TEST(IOVectorTest, Append) { - IOVector iov; - int length = 0; - const struct iovec* iov2 = iov.iovec(); - - ASSERT_EQ(0u, iov.Size()); - ASSERT_TRUE(iov2 == nullptr); - for (size_t i = 0; i < arraysize(test_data); ++i) { - const int str_len = strlen(test_data[i]); - const int append_len = str_len / 2; - // This should append a new block. - iov.Append(const_cast(test_data[i]), append_len); - length += append_len; - ASSERT_EQ(i + 1, static_cast(iov.Size())); - ASSERT_TRUE(iov.LastBlockEnd() == test_data[i] + append_len); - // This should just lengthen the existing block. - iov.Append(const_cast(test_data[i] + append_len), - str_len - append_len); - length += (str_len - append_len); - ASSERT_EQ(i + 1, static_cast(iov.Size())); - ASSERT_TRUE(iov.LastBlockEnd() == test_data[i] + str_len); - } - - iov2 = iov.iovec(); - ASSERT_TRUE(iov2 != nullptr); - for (size_t i = 0; i < iov.Size(); ++i) { - ASSERT_TRUE(test_data[i] == iov2[i].iov_base); - ASSERT_EQ(strlen(test_data[i]), iov2[i].iov_len); - } -} - -TEST(IOVectorTest, AppendIovec) { - IOVector iov; - const struct iovec test_iov[] = {{const_cast("foo"), 3}, - {const_cast("bar"), 3}, - {const_cast("buzzzz"), 6}}; - iov.AppendIovec(test_iov, arraysize(test_iov)); - for (size_t i = 0; i < arraysize(test_iov); ++i) { - EXPECT_EQ(test_iov[i].iov_base, iov.iovec()[i].iov_base); - EXPECT_EQ(test_iov[i].iov_len, iov.iovec()[i].iov_len); - } - - // Test AppendIovecAtMostBytes. - iov.Clear(); - // Stop in the middle of a block. - EXPECT_EQ(5u, iov.AppendIovecAtMostBytes(test_iov, arraysize(test_iov), 5)); - EXPECT_EQ(5u, iov.TotalBufferSize()); - iov.Append(static_cast(test_iov[1].iov_base) + 2, 1); - // Make sure the boundary case, where max_bytes == size of block also works. - EXPECT_EQ(6u, iov.AppendIovecAtMostBytes(&test_iov[2], 1, 6)); - ASSERT_LE(arraysize(test_iov), static_cast(iov.Size())); - for (size_t i = 0; i < arraysize(test_iov); ++i) { - EXPECT_EQ(test_iov[i].iov_base, iov.iovec()[i].iov_base); - EXPECT_EQ(test_iov[i].iov_len, iov.iovec()[i].iov_len); - } -} - -TEST(IOVectorTest, ConsumeHalfBlocks) { - IOVector iov; - int length = 0; - - for (size_t i = 0; i < arraysize(test_data); ++i) { - const int str_len = strlen(test_data[i]); - iov.Append(const_cast(test_data[i]), str_len); - length += str_len; - } - const char* endp = iov.LastBlockEnd(); - for (size_t i = 0; i < arraysize(test_data); ++i) { - const struct iovec* iov2 = iov.iovec(); - const size_t str_len = strlen(test_data[i]); - size_t tmp = str_len / 2; - - ASSERT_TRUE(iov2 != nullptr); - ASSERT_TRUE(iov2[0].iov_base == test_data[i]); - ASSERT_EQ(str_len, iov2[0].iov_len); - - // Consume half of the first block. - size_t consumed = iov.Consume(tmp); - ASSERT_EQ(tmp, consumed); - ASSERT_EQ(arraysize(test_data) - i, static_cast(iov.Size())); - iov2 = iov.iovec(); - ASSERT_TRUE(iov2 != nullptr); - ASSERT_TRUE(iov2[0].iov_base == test_data[i] + tmp); - ASSERT_EQ(iov2[0].iov_len, str_len - tmp); - - // Consume the rest of the first block. - consumed = iov.Consume(str_len - tmp); - ASSERT_EQ(str_len - tmp, consumed); - ASSERT_EQ(arraysize(test_data) - i - 1, static_cast(iov.Size())); - iov2 = iov.iovec(); - if (iov.Size() > 0) { - ASSERT_TRUE(iov2 != nullptr); - ASSERT_TRUE(iov.LastBlockEnd() == endp); - } else { - ASSERT_TRUE(iov2 == nullptr); - ASSERT_TRUE(iov.LastBlockEnd() == nullptr); - } - } -} - -TEST(IOVectorTest, ConsumeTwoAndHalfBlocks) { - IOVector iov; - int length = 0; - - for (size_t i = 0; i < arraysize(test_data); ++i) { - const int str_len = strlen(test_data[i]); - iov.Append(const_cast(test_data[i]), str_len); - length += str_len; - } - const size_t last_len = strlen(test_data[arraysize(test_data) - 1]); - const size_t half_len = last_len / 2; - - const char* endp = iov.LastBlockEnd(); - size_t consumed = iov.Consume(length - half_len); - ASSERT_EQ(length - half_len, consumed); - const struct iovec* iov2 = iov.iovec(); - ASSERT_TRUE(iov2 != nullptr); - ASSERT_EQ(1u, iov.Size()); - ASSERT_TRUE(iov2[0].iov_base == - test_data[arraysize(test_data) - 1] + last_len - half_len); - ASSERT_EQ(half_len, iov2[0].iov_len); - ASSERT_TRUE(iov.LastBlockEnd() == endp); - - consumed = iov.Consume(half_len); - ASSERT_EQ(half_len, consumed); - iov2 = iov.iovec(); - ASSERT_EQ(0u, iov.Size()); - ASSERT_TRUE(iov2 == nullptr); - ASSERT_TRUE(iov.LastBlockEnd() == nullptr); -} - -TEST(IOVectorTest, ConsumeTooMuch) { - IOVector iov; - int length = 0; - - for (size_t i = 0; i < arraysize(test_data); ++i) { - const int str_len = strlen(test_data[i]); - iov.Append(const_cast(test_data[i]), str_len); - length += str_len; - } - - int consumed = 0; - EXPECT_DFATAL({ consumed = iov.Consume(length + 1); }, - "Attempting to consume 1 non-existent bytes."); - ASSERT_EQ(length, consumed); - const struct iovec* iov2 = iov.iovec(); - ASSERT_EQ(0u, iov.Size()); - ASSERT_TRUE(iov2 == nullptr); - ASSERT_TRUE(iov.LastBlockEnd() == nullptr); -} - -TEST(IOVectorTest, ConsumeAndCopyHalfBlocks) { - IOVector iov; - int length = 0; - - for (size_t i = 0; i < arraysize(test_data); ++i) { - const int str_len = strlen(test_data[i]); - iov.Append(const_cast(test_data[i]), str_len); - length += str_len; - } - const char* endp = iov.LastBlockEnd(); - for (size_t i = 0; i < arraysize(test_data); ++i) { - const struct iovec* iov2 = iov.iovec(); - const size_t str_len = strlen(test_data[i]); - size_t tmp = str_len / 2; - - ASSERT_TRUE(iov2 != nullptr); - ASSERT_TRUE(iov2[0].iov_base == test_data[i]); - ASSERT_EQ(str_len, iov2[0].iov_len); - - // Consume half of the first block. - std::unique_ptr buffer(new char[str_len]); - size_t consumed = iov.ConsumeAndCopy(tmp, buffer.get()); - EXPECT_EQ(0, memcmp(test_data[i], buffer.get(), tmp)); - ASSERT_EQ(tmp, consumed); - ASSERT_EQ(arraysize(test_data) - i, static_cast(iov.Size())); - iov2 = iov.iovec(); - ASSERT_TRUE(iov2 != nullptr); - ASSERT_TRUE(iov2[0].iov_base == test_data[i] + tmp); - ASSERT_EQ(iov2[0].iov_len, str_len - tmp); - - // Consume the rest of the first block. - consumed = iov.ConsumeAndCopy(str_len - tmp, buffer.get()); - ASSERT_EQ(str_len - tmp, consumed); - ASSERT_EQ(arraysize(test_data) - i - 1, static_cast(iov.Size())); - iov2 = iov.iovec(); - if (iov.Size() > 0) { - ASSERT_TRUE(iov2 != nullptr); - ASSERT_TRUE(iov.LastBlockEnd() == endp); - } else { - ASSERT_TRUE(iov2 == nullptr); - ASSERT_TRUE(iov.LastBlockEnd() == nullptr); - } - } -} - -TEST(IOVectorTest, ConsumeAndCopyTwoAndHalfBlocks) { - IOVector iov; - size_t length = 0; - - for (size_t i = 0; i < arraysize(test_data); ++i) { - const int str_len = strlen(test_data[i]); - iov.Append(const_cast(test_data[i]), str_len); - length += str_len; - } - const size_t last_len = strlen(test_data[arraysize(test_data) - 1]); - const size_t half_len = last_len / 2; - - const char* endp = iov.LastBlockEnd(); - std::unique_ptr buffer(new char[length]); - size_t consumed = iov.ConsumeAndCopy(length - half_len, buffer.get()); - ASSERT_EQ(length - half_len, consumed); - const struct iovec* iov2 = iov.iovec(); - ASSERT_TRUE(iov2 != nullptr); - ASSERT_EQ(1u, iov.Size()); - ASSERT_TRUE(iov2[0].iov_base == - test_data[arraysize(test_data) - 1] + last_len - half_len); - ASSERT_EQ(half_len, iov2[0].iov_len); - ASSERT_TRUE(iov.LastBlockEnd() == endp); - - consumed = iov.Consume(half_len); - ASSERT_EQ(half_len, consumed); - iov2 = iov.iovec(); - ASSERT_EQ(0u, iov.Size()); - ASSERT_TRUE(iov2 == nullptr); - ASSERT_TRUE(iov.LastBlockEnd() == nullptr); -} - -TEST(IOVectorTest, ConsumeAndCopyTooMuch) { - IOVector iov; - int length = 0; - - for (size_t i = 0; i < arraysize(test_data); ++i) { - const int str_len = strlen(test_data[i]); - iov.Append(const_cast(test_data[i]), str_len); - length += str_len; - } - - int consumed = 0; - std::unique_ptr buffer(new char[length + 1]); - EXPECT_DFATAL({ consumed = iov.ConsumeAndCopy(length + 1, buffer.get()); }, - "Attempting to consume 1 non-existent bytes."); - ASSERT_EQ(length, consumed); - const struct iovec* iov2 = iov.iovec(); - ASSERT_EQ(0u, iov.Size()); - ASSERT_TRUE(iov2 == nullptr); - ASSERT_TRUE(iov.LastBlockEnd() == nullptr); -} - -TEST(IOVectorTest, Clear) { - IOVector iov; - int length = 0; - - for (size_t i = 0; i < arraysize(test_data); ++i) { - const int str_len = strlen(test_data[i]); - iov.Append(const_cast(test_data[i]), str_len); - length += str_len; - } - const struct iovec* iov2 = iov.iovec(); - ASSERT_TRUE(iov2 != nullptr); - ASSERT_EQ(arraysize(test_data), static_cast(iov.Size())); - - iov.Clear(); - iov2 = iov.iovec(); - ASSERT_EQ(0u, iov.Size()); - ASSERT_TRUE(iov2 == nullptr); -} - -TEST(IOVectorTest, Capacity) { - IOVector iov; - // Note: IOVector merges adjacent Appends() into a single iov. - // Therefore, if we expect final size of iov to be 3, we must insure - // that the items we are appending are not adjacent. To achieve that - // we use use an array (a[1] provides a buffer between a[0] and b[0], - // and makes them non-adjacent). - char a[2], b[2], c[2]; - iov.Append(&a[0], 1); - iov.Append(&b[0], 1); - iov.Append(&c[0], 1); - ASSERT_EQ(3u, iov.Size()); - size_t capacity = iov.Capacity(); - EXPECT_LE(iov.Size(), capacity); - iov.Consume(2); - // The capacity should not have changed. - EXPECT_EQ(capacity, iov.Capacity()); -} - -TEST(IOVectorTest, Swap) { - IOVector iov1, iov2; - // See IOVector merge comment above. - char a[2], b[2], c[2], d[2], e[2]; - iov1.Append(&a[0], 1); - iov1.Append(&b[0], 1); - - iov2.Append(&c[0], 1); - iov2.Append(&d[0], 1); - iov2.Append(&e[0], 1); - iov1.Swap(&iov2); - - ASSERT_EQ(3u, iov1.Size()); - EXPECT_EQ(&c[0], iov1.iovec()[0].iov_base); - EXPECT_EQ(1u, iov1.iovec()[0].iov_len); - EXPECT_EQ(&d[0], iov1.iovec()[1].iov_base); - EXPECT_EQ(1u, iov1.iovec()[1].iov_len); - EXPECT_EQ(&e[0], iov1.iovec()[2].iov_base); - EXPECT_EQ(1u, iov1.iovec()[2].iov_len); - - ASSERT_EQ(2u, iov2.Size()); - EXPECT_EQ(&a[0], iov2.iovec()[0].iov_base); - EXPECT_EQ(1u, iov2.iovec()[0].iov_len); - EXPECT_EQ(&b[0], iov2.iovec()[1].iov_base); - EXPECT_EQ(1u, iov2.iovec()[1].iov_len); -} - -} // namespace -} // namespace test -} // namespace net diff --git a/net/quic/core/reliable_quic_stream.cc b/net/quic/core/reliable_quic_stream.cc index 79880dc6a2efd0..1c71776d56ef57 100644 --- a/net/quic/core/reliable_quic_stream.cc +++ b/net/quic/core/reliable_quic_stream.cc @@ -5,7 +5,6 @@ #include "net/quic/core/reliable_quic_stream.h" #include "base/logging.h" -#include "net/quic/core/iovector.h" #include "net/quic/core/quic_bug_tracker.h" #include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_flow_controller.h" @@ -275,7 +274,12 @@ QuicConsumedData ReliableQuicStream::WritevData( } // How much data was provided. - size_t write_length = TotalIovecLength(iov, iov_count); + size_t write_length = 0; + if (iov != nullptr) { + for (int i = 0; i < iov_count; ++i) { + write_length += iov[i].iov_len; + } + } // A FIN with zero data payload should not be flow control blocked. bool fin_with_zero_data = (fin && write_length == 0);