diff --git a/rtc_base/bytebuffer.cc b/rtc_base/bytebuffer.cc index ea4de3a696..f152d4f1f1 100644 --- a/rtc_base/bytebuffer.cc +++ b/rtc_base/bytebuffer.cc @@ -15,126 +15,21 @@ #include #include "rtc_base/basictypes.h" -#include "rtc_base/byteorder.h" namespace rtc { -static const int DEFAULT_SIZE = 4096; - -ByteBufferWriter::ByteBufferWriter() - : ByteBuffer(ORDER_NETWORK) { - Construct(nullptr, DEFAULT_SIZE); -} +ByteBufferWriter::ByteBufferWriter() : ByteBufferWriterT() {} ByteBufferWriter::ByteBufferWriter(ByteOrder byte_order) - : ByteBuffer(byte_order) { - Construct(nullptr, DEFAULT_SIZE); -} + : ByteBufferWriterT(byte_order) {} ByteBufferWriter::ByteBufferWriter(const char* bytes, size_t len) - : ByteBuffer(ORDER_NETWORK) { - Construct(bytes, len); -} + : ByteBufferWriterT(bytes, len) {} -ByteBufferWriter::ByteBufferWriter(const char* bytes, size_t len, +ByteBufferWriter::ByteBufferWriter(const char* bytes, + size_t len, ByteOrder byte_order) - : ByteBuffer(byte_order) { - Construct(bytes, len); -} - -void ByteBufferWriter::Construct(const char* bytes, size_t len) { - size_ = len; - bytes_ = new char[size_]; - - if (bytes) { - end_ = len; - memcpy(bytes_, bytes, end_); - } else { - end_ = 0; - } -} - -ByteBufferWriter::~ByteBufferWriter() { - delete[] bytes_; -} - -void ByteBufferWriter::WriteUInt8(uint8_t val) { - WriteBytes(reinterpret_cast(&val), 1); -} - -void ByteBufferWriter::WriteUInt16(uint16_t val) { - uint16_t v = (Order() == ORDER_NETWORK) ? HostToNetwork16(val) : val; - WriteBytes(reinterpret_cast(&v), 2); -} - -void ByteBufferWriter::WriteUInt24(uint32_t val) { - uint32_t v = (Order() == ORDER_NETWORK) ? HostToNetwork32(val) : val; - char* start = reinterpret_cast(&v); - if (Order() == ORDER_NETWORK || IsHostBigEndian()) { - ++start; - } - WriteBytes(start, 3); -} - -void ByteBufferWriter::WriteUInt32(uint32_t val) { - uint32_t v = (Order() == ORDER_NETWORK) ? HostToNetwork32(val) : val; - WriteBytes(reinterpret_cast(&v), 4); -} - -void ByteBufferWriter::WriteUInt64(uint64_t val) { - uint64_t v = (Order() == ORDER_NETWORK) ? HostToNetwork64(val) : val; - WriteBytes(reinterpret_cast(&v), 8); -} - -// Serializes an unsigned varint in the format described by -// https://developers.google.com/protocol-buffers/docs/encoding#varints -// with the caveat that integers are 64-bit, not 128-bit. -void ByteBufferWriter::WriteUVarint(uint64_t val) { - while (val >= 0x80) { - // Write 7 bits at a time, then set the msb to a continuation byte (msb=1). - char byte = static_cast(val) | 0x80; - WriteBytes(&byte, 1); - val >>= 7; - } - char last_byte = static_cast(val); - WriteBytes(&last_byte, 1); -} - -void ByteBufferWriter::WriteString(const std::string& val) { - WriteBytes(val.c_str(), val.size()); -} - -void ByteBufferWriter::WriteBytes(const char* val, size_t len) { - memcpy(ReserveWriteBuffer(len), val, len); -} - -char* ByteBufferWriter::ReserveWriteBuffer(size_t len) { - if (Length() + len > Capacity()) - Resize(Length() + len); - - char* start = bytes_ + end_; - end_ += len; - return start; -} - -void ByteBufferWriter::Resize(size_t size) { - size_t len = std::min(end_, size); - if (size > size_) { - // Reallocate a larger buffer. - size_ = std::max(size, 3 * size_ / 2); - char* new_bytes = new char[size_]; - memcpy(new_bytes, bytes_, len); - delete [] bytes_; - bytes_ = new_bytes; - } - end_ = len; -} - -void ByteBufferWriter::Clear() { - memset(bytes_, 0, size_); - end_ = 0; -} - + : ByteBufferWriterT(bytes, len, byte_order) {} ByteBufferReader::ByteBufferReader(const char* bytes, size_t len) : ByteBuffer(ORDER_NETWORK) { diff --git a/rtc_base/bytebuffer.h b/rtc_base/bytebuffer.h index c7aa1607c3..740bff2c72 100644 --- a/rtc_base/bytebuffer.h +++ b/rtc_base/bytebuffer.h @@ -15,6 +15,7 @@ #include "rtc_base/basictypes.h" #include "rtc_base/buffer.h" +#include "rtc_base/byteorder.h" #include "rtc_base/constructormagic.h" namespace rtc { @@ -36,7 +37,105 @@ class ByteBuffer { RTC_DISALLOW_COPY_AND_ASSIGN(ByteBuffer); }; -class ByteBufferWriter : public ByteBuffer { +template +class ByteBufferWriterT : public ByteBuffer { + public: + // |byte_order| defines order of bytes in the buffer. + ByteBufferWriterT() : ByteBuffer(ORDER_NETWORK) { + Construct(nullptr, kDefaultCapacity); + } + explicit ByteBufferWriterT(ByteOrder byte_order) : ByteBuffer(byte_order) { + Construct(nullptr, kDefaultCapacity); + } + ByteBufferWriterT(const char* bytes, size_t len) : ByteBuffer(ORDER_NETWORK) { + Construct(bytes, len); + } + ByteBufferWriterT(const char* bytes, size_t len, ByteOrder byte_order) + : ByteBuffer(byte_order) { + Construct(bytes, len); + } + + const char* Data() const { return buffer_.data(); } + size_t Length() const { return buffer_.size(); } + size_t Capacity() const { return buffer_.capacity(); } + + // Write value to the buffer. Resizes the buffer when it is + // neccessary. + void WriteUInt8(uint8_t val) { + WriteBytes(reinterpret_cast(&val), 1); + } + void WriteUInt16(uint16_t val) { + uint16_t v = (Order() == ORDER_NETWORK) ? HostToNetwork16(val) : val; + WriteBytes(reinterpret_cast(&v), 2); + } + void WriteUInt24(uint32_t val) { + uint32_t v = (Order() == ORDER_NETWORK) ? HostToNetwork32(val) : val; + char* start = reinterpret_cast(&v); + if (Order() == ORDER_NETWORK || IsHostBigEndian()) { + ++start; + } + WriteBytes(start, 3); + } + void WriteUInt32(uint32_t val) { + uint32_t v = (Order() == ORDER_NETWORK) ? HostToNetwork32(val) : val; + WriteBytes(reinterpret_cast(&v), 4); + } + void WriteUInt64(uint64_t val) { + uint64_t v = (Order() == ORDER_NETWORK) ? HostToNetwork64(val) : val; + WriteBytes(reinterpret_cast(&v), 8); + } + // Serializes an unsigned varint in the format described by + // https://developers.google.com/protocol-buffers/docs/encoding#varints + // with the caveat that integers are 64-bit, not 128-bit. + void WriteUVarint(uint64_t val) { + while (val >= 0x80) { + // Write 7 bits at a time, then set the msb to a continuation byte + // (msb=1). + char byte = static_cast(val) | 0x80; + WriteBytes(&byte, 1); + val >>= 7; + } + char last_byte = static_cast(val); + WriteBytes(&last_byte, 1); + } + void WriteString(const std::string& val) { + WriteBytes(val.c_str(), val.size()); + } + void WriteBytes(const char* val, size_t len) { buffer_.AppendData(val, len); } + + // Reserves the given number of bytes and returns a char* that can be written + // into. Useful for functions that require a char* buffer and not a + // ByteBufferWriter. + char* ReserveWriteBuffer(size_t len) { + buffer_.SetSize(buffer_.size() + len); + return buffer_.data(); + } + + // Resize the buffer to the specified |size|. + void Resize(size_t size) { buffer_.SetSize(size); } + + // Clears the contents of the buffer. After this, Length() will be 0. + void Clear() { buffer_.Clear(); } + + private: + static constexpr size_t kDefaultCapacity = 4096; + + void Construct(const char* bytes, size_t size) { + if (bytes) { + buffer_.AppendData(bytes, size); + } else { + buffer_.EnsureCapacity(size); + } + } + + BufferClassT buffer_; + + // There are sensible ways to define these, but they aren't needed in our code + // base. + RTC_DISALLOW_COPY_AND_ASSIGN(ByteBufferWriterT); +}; + +class ByteBufferWriter : public ByteBufferWriterT> { public: // |byte_order| defines order of bytes in the buffer. ByteBufferWriter(); @@ -44,44 +143,7 @@ class ByteBufferWriter : public ByteBuffer { ByteBufferWriter(const char* bytes, size_t len); ByteBufferWriter(const char* bytes, size_t len, ByteOrder byte_order); - ~ByteBufferWriter(); - - const char* Data() const { return bytes_; } - char* MutableData() { return bytes_; } - size_t Length() const { return end_; } - size_t Capacity() const { return size_; } - - // Write value to the buffer. Resizes the buffer when it is - // neccessary. - void WriteUInt8(uint8_t val); - void WriteUInt16(uint16_t val); - void WriteUInt24(uint32_t val); - void WriteUInt32(uint32_t val); - void WriteUInt64(uint64_t val); - void WriteUVarint(uint64_t val); - void WriteString(const std::string& val); - void WriteBytes(const char* val, size_t len); - - // Reserves the given number of bytes and returns a char* that can be written - // into. Useful for functions that require a char* buffer and not a - // ByteBufferWriter. - char* ReserveWriteBuffer(size_t len); - - // Resize the buffer to the specified |size|. - void Resize(size_t size); - - // Clears the contents of the buffer. After this, Length() will be 0. - void Clear(); - private: - void Construct(const char* bytes, size_t size); - - char* bytes_; - size_t size_; - size_t end_; - - // There are sensible ways to define these, but they aren't needed in our code - // base. RTC_DISALLOW_COPY_AND_ASSIGN(ByteBufferWriter); }; diff --git a/rtc_base/socketadapters.cc b/rtc_base/socketadapters.cc index 5b95cac928..a3004951b0 100644 --- a/rtc_base/socketadapters.cc +++ b/rtc_base/socketadapters.cc @@ -665,7 +665,7 @@ void AsyncSocksProxySocket::SendHello() { } void AsyncSocksProxySocket::SendAuth() { - ByteBufferWriter request; + ByteBufferWriterT> request; request.WriteUInt8(1); // Negotiation Version request.WriteUInt8(static_cast(user_.size())); request.WriteString(user_); // Username @@ -673,14 +673,10 @@ void AsyncSocksProxySocket::SendAuth() { size_t len = pass_.GetLength() + 1; char * sensitive = new char[len]; pass_.CopyTo(sensitive, true); - // Don't write anything to |request| afterwards to avoid potential - // reallocations where the old memory (containing the password) will not - // be cleared securely. request.WriteBytes(sensitive, pass_.GetLength()); // Password ExplicitZeroMemory(sensitive, len); delete [] sensitive; DirectSend(request.Data(), request.Length()); - ExplicitZeroMemory(request.MutableData(), request.Length()); state_ = SS_AUTH; }