11e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 21e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 31e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// found in the LICENSE file. 41e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 51e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#ifndef NET_QUIC_IOVECTOR_H_ 61e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#define NET_QUIC_IOVECTOR_H_ 71e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 81e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <stddef.h> 91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <algorithm> 101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <vector> 111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/basictypes.h" 131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/logging.h" 141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "net/base/iovec.h" 151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "net/base/net_export.h" 161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace net { 181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Calculate the total number of bytes in an array of iovec structures. 201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)inline size_t TotalIovecLength(const struct iovec* iov, size_t iovcnt) { 211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) size_t length = 0; 221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (iov != NULL) { 231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) for (size_t i = 0; i < iovcnt; ++i) { 241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) length += iov[i].iov_len; 251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return length; 281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// IOVector is a helper class that makes it easier to work with POSIX vector I/O 311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// struct. It is a thin wrapper by design and thus has no virtual functions and 321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// all inlined methods. This class makes no assumptions about the ordering of 331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// the pointer values of the blocks appended, it simply counts bytes when asked 341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// to consume bytes. 351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// 361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// IOVector is a bookkeeping object that collects a description of buffers to 371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// be read or written together and in order. It does not take ownership of the 381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// blocks appended. 391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// 401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Because it is used for scatter-gather operations, the order in which the 411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// buffer blocks are added to the IOVector is important to the client. The 421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// intended usage pattern is: 431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// 441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// iovector.Append(p0, len0); 451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// ... 461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// iovector.Append(pn, lenn); 471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// int bytes_written = writev(fd, iovector.iovec(), iovector.Size()); 481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// if (bytes_written > 0) 491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// iovector.Consume(bytes_written); 501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// 511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// The sequence is the same for readv, except that Consume() in this case is 521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// used to change the IOVector to only keep track of description of blocks of 531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// memory not yet written to. 541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// 551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// IOVector does not have any method to change the iovec entries that it 561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// accumulates. This is due to the block merging nature of Append(): we'd like 571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// to avoid accidentally change an entry that is assembled by two or more 581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Append()'s by simply an index access. 591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// 601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)class NET_EXPORT_PRIVATE IOVector { 621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) public: 631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Provide a default constructor so it'll never be inhibited by adding other 641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // constructors. 651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) IOVector(); 661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ~IOVector(); 671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Provides a way to convert system call-like iovec representation to 691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // IOVector. 701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) void AppendIovec(const struct iovec* iov, size_t iovcnt) { 711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) for (size_t i = 0; i < iovcnt; ++i) 721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Append(static_cast<char*>(iov[i].iov_base), iov[i].iov_len); 731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Appends at most max_bytes from iovec to the IOVector. 761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) size_t AppendIovecAtMostBytes(const struct iovec* iov, 771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) size_t iovcnt, 781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) size_t max_bytes) { 791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) size_t bytes_appended = 0; 801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) for (size_t i = 0; i < iovcnt && max_bytes > 0; ++i) { 811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const size_t length = std::min(max_bytes, iov[i].iov_len); 821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Append(static_cast<char*>(iov[i].iov_base), length); 831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) max_bytes -= length; 841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bytes_appended += length; 851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return bytes_appended; 871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Append another block to the IOVector. Since IOVector can be used for read 901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // and write, it always takes char*. Clients that writes will need to cast 911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // away the constant of the pointer before appending a block. 921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) void Append(char* buffer, size_t length) { 931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (buffer != NULL && length > 0) { 941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (iovec_.size() > 0) { 951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) struct iovec& last = iovec_.back(); 961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // If the new block is contiguous with the last block, just extend. 971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (static_cast<char*>(last.iov_base) + last.iov_len == buffer) { 981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) last.iov_len += length; 991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return; 1001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) struct iovec tmp = {buffer, length}; 1031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) iovec_.push_back(tmp); 1041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Same as Append, but doesn't do the tail merge optimization. 1081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Intended for testing. 1091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) void AppendNoCoalesce(char* buffer, size_t length) { 1101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (buffer != NULL && length > 0) { 1111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) struct iovec tmp = {buffer, length}; 1121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) iovec_.push_back(tmp); 1131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Remove a number of bytes from the beginning of the IOVector. Since vector 1171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // I/O operations always occur at the beginning of the block list, a method 1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // to remove bytes at the end is not provided. 1191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // It returns the number of bytes actually consumed (it'll only be smaller 1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // than the requested number if the IOVector contains less data). 1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) size_t Consume(size_t length) { 1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (length == 0) return 0; 1231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) size_t bytes_to_consume = length; 1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::vector<struct iovec>::iterator iter = iovec_.begin(); 1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::vector<struct iovec>::iterator end = iovec_.end(); 1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) for (; iter < end && bytes_to_consume >= iter->iov_len; ++iter) { 1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bytes_to_consume -= iter->iov_len; 1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) iovec_.erase(iovec_.begin(), iter); 1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (iovec_.size() > 0 && bytes_to_consume != 0) { 1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) iovec_[0].iov_base = 1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static_cast<char*>(iovec_[0].iov_base) + bytes_to_consume; 1341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) iovec_[0].iov_len -= bytes_to_consume; 1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return length; 1361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (iovec_.size() == 0 && bytes_to_consume > 0) { 1381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) LOG(DFATAL) << "Attempting to consume " << bytes_to_consume 1391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) << " non-existent bytes."; 1401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // At this point bytes_to_consume is the number of wanted bytes left over 1421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // after walking through all the iovec entries. 1431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return length - bytes_to_consume; 1441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // TODO(joechan): If capacity is large, swap out for a blank one. 1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Clears the IOVector object to contain no blocks. 1481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) void Clear() { iovec_.clear(); } 1491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Swap the guts of two IOVector. 1511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) void Swap(IOVector* other) { iovec_.swap(other->iovec_); } 1521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Returns the number of valid blocks in the IOVector (not the number of 1541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // bytes). 1551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) size_t Size() const { return iovec_.size(); } 1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Returns the total storage used by the IOVector in number of blocks (not 1581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // the number of bytes). 1591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) size_t Capacity() const { return iovec_.capacity(); } 1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Returns true if there are no blocks in the IOVector. 1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bool Empty() const { return iovec_.empty(); } 1631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Returns the pointer to the beginning of the iovec to be used for vector 1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // I/O operations. If the IOVector has no blocks appened, this function 1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // returns NULL. 1671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) struct iovec* iovec() { return !Empty() ? &iovec_[0] : NULL; } 1681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Const version. 1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const struct iovec* iovec() const { return !Empty() ? &iovec_[0] : NULL; } 1711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Returns a pointer to one past the last byte of the last block. If the 1731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // IOVector is empty, NULL is returned. 1741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const char* LastBlockEnd() const { 1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return iovec_.size() > 0 ? 1761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static_cast<char *>(iovec_.back().iov_base) + iovec_.back().iov_len : 1771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) NULL; 1781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Returns the total number of bytes in the IOVector. 1811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) size_t TotalBufferSize() const { return TotalIovecLength(iovec(), Size()); } 1821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) void Resize(size_t count) { 1841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) iovec_.resize(count); 1851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) private: 1881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::vector<struct iovec> iovec_; 1891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // IOVector has value-semantics; copy and assignment are allowed. 1911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // This class does not explicitly define copy/move constructors or the 1921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // assignment operator to preserve compiler-generated copy/move constructors 1931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // and assignment operators. Note that since IOVector does not own the 1941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // actual buffers that the struct iovecs point to, copies and assignments 1951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // result in a shallow copy of the buffers; resulting IOVectors will point 1961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // to the same copy of the underlying data. 1971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}; 1981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} // namespace net 2001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#endif // NET_QUIC_IOVECTOR_H_ 202