Split ByteBuffer into writer/reader objects.

This allows the reader to reference data, thus avoiding unnecessary
allocations and memory copies.

BUG=webrtc:5155,webrtc:5670

Review URL: https://codereview.webrtc.org/1821083002

Cr-Commit-Position: refs/heads/master@{#12160}
diff --git a/webrtc/api/sctputils.cc b/webrtc/api/sctputils.cc
index f2d1b0f..d6ea601 100644
--- a/webrtc/api/sctputils.cc
+++ b/webrtc/api/sctputils.cc
@@ -49,9 +49,7 @@
   // Format defined at
   // http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04
 
-  // TODO(jbauch): avoid copying the payload data into the ByteBuffer, see
-  // https://bugs.chromium.org/p/webrtc/issues/detail?id=5670
-  rtc::ByteBuffer buffer(payload.data<char>(), payload.size());
+  rtc::ByteBufferReader buffer(payload.data<char>(), payload.size());
   uint8_t message_type;
   if (!buffer.ReadUInt8(&message_type)) {
     LOG(LS_WARNING) << "Could not read OPEN message type.";
@@ -166,7 +164,7 @@
     }
   }
 
-  rtc::ByteBuffer buffer(
+  rtc::ByteBufferWriter buffer(
       NULL, 20 + label.length() + config.protocol.length(),
       rtc::ByteBuffer::ORDER_NETWORK);
   // TODO(tommi): Add error handling and check resulting length.
diff --git a/webrtc/base/bitbuffer_unittest.cc b/webrtc/base/bitbuffer_unittest.cc
index ce42257..7ba9c73 100644
--- a/webrtc/base/bitbuffer_unittest.cc
+++ b/webrtc/base/bitbuffer_unittest.cc
@@ -188,7 +188,7 @@
 }
 
 TEST(BitBufferTest, GolombUint32Values) {
-  ByteBuffer byteBuffer;
+  ByteBufferWriter byteBuffer;
   byteBuffer.Resize(16);
   BitBuffer buffer(reinterpret_cast<const uint8_t*>(byteBuffer.Data()),
                    byteBuffer.Capacity());
diff --git a/webrtc/base/bytebuffer.cc b/webrtc/base/bytebuffer.cc
index 8bc1f23..cf4ce42 100644
--- a/webrtc/base/bytebuffer.cc
+++ b/webrtc/base/bytebuffer.cc
@@ -22,36 +22,30 @@
 
 static const int DEFAULT_SIZE = 4096;
 
-ByteBuffer::ByteBuffer() {
-  Construct(NULL, DEFAULT_SIZE, ORDER_NETWORK);
+ByteBufferWriter::ByteBufferWriter()
+    : ByteBuffer(ORDER_NETWORK) {
+  Construct(NULL, DEFAULT_SIZE);
 }
 
-ByteBuffer::ByteBuffer(ByteOrder byte_order) {
-  Construct(NULL, DEFAULT_SIZE, byte_order);
+ByteBufferWriter::ByteBufferWriter(ByteOrder byte_order)
+    : ByteBuffer(byte_order) {
+  Construct(NULL, DEFAULT_SIZE);
 }
 
-ByteBuffer::ByteBuffer(const char* bytes, size_t len) {
-  Construct(bytes, len, ORDER_NETWORK);
+ByteBufferWriter::ByteBufferWriter(const char* bytes, size_t len)
+    : ByteBuffer(ORDER_NETWORK) {
+  Construct(bytes, len);
 }
 
-ByteBuffer::ByteBuffer(const char* bytes, size_t len, ByteOrder byte_order) {
-  Construct(bytes, len, byte_order);
+ByteBufferWriter::ByteBufferWriter(const char* bytes, size_t len,
+                                   ByteOrder byte_order)
+    : ByteBuffer(byte_order) {
+  Construct(bytes, len);
 }
 
-ByteBuffer::ByteBuffer(const char* bytes) {
-  Construct(bytes, strlen(bytes), ORDER_NETWORK);
-}
-
-ByteBuffer::ByteBuffer(const Buffer& buf) {
-  Construct(buf.data<char>(), buf.size(), ORDER_NETWORK);
-}
-
-void ByteBuffer::Construct(const char* bytes, size_t len,
-                           ByteOrder byte_order) {
-  version_ = 0;
+void ByteBufferWriter::Construct(const char* bytes, size_t len) {
   start_ = 0;
   size_ = len;
-  byte_order_ = byte_order;
   bytes_ = new char[size_];
 
   if (bytes) {
@@ -62,128 +56,47 @@
   }
 }
 
-ByteBuffer::~ByteBuffer() {
+ByteBufferWriter::~ByteBufferWriter() {
   delete[] bytes_;
 }
 
-bool ByteBuffer::ReadUInt8(uint8_t* val) {
-  if (!val) return false;
-
-  return ReadBytes(reinterpret_cast<char*>(val), 1);
-}
-
-bool ByteBuffer::ReadUInt16(uint16_t* val) {
-  if (!val) return false;
-
-  uint16_t v;
-  if (!ReadBytes(reinterpret_cast<char*>(&v), 2)) {
-    return false;
-  } else {
-    *val = (byte_order_ == ORDER_NETWORK) ? NetworkToHost16(v) : v;
-    return true;
-  }
-}
-
-bool ByteBuffer::ReadUInt24(uint32_t* val) {
-  if (!val) return false;
-
-  uint32_t v = 0;
-  char* read_into = reinterpret_cast<char*>(&v);
-  if (byte_order_ == ORDER_NETWORK || IsHostBigEndian()) {
-    ++read_into;
-  }
-
-  if (!ReadBytes(read_into, 3)) {
-    return false;
-  } else {
-    *val = (byte_order_ == ORDER_NETWORK) ? NetworkToHost32(v) : v;
-    return true;
-  }
-}
-
-bool ByteBuffer::ReadUInt32(uint32_t* val) {
-  if (!val) return false;
-
-  uint32_t v;
-  if (!ReadBytes(reinterpret_cast<char*>(&v), 4)) {
-    return false;
-  } else {
-    *val = (byte_order_ == ORDER_NETWORK) ? NetworkToHost32(v) : v;
-    return true;
-  }
-}
-
-bool ByteBuffer::ReadUInt64(uint64_t* val) {
-  if (!val) return false;
-
-  uint64_t v;
-  if (!ReadBytes(reinterpret_cast<char*>(&v), 8)) {
-    return false;
-  } else {
-    *val = (byte_order_ == ORDER_NETWORK) ? NetworkToHost64(v) : v;
-    return true;
-  }
-}
-
-bool ByteBuffer::ReadString(std::string* val, size_t len) {
-  if (!val) return false;
-
-  if (len > Length()) {
-    return false;
-  } else {
-    val->append(bytes_ + start_, len);
-    start_ += len;
-    return true;
-  }
-}
-
-bool ByteBuffer::ReadBytes(char* val, size_t len) {
-  if (len > Length()) {
-    return false;
-  } else {
-    memcpy(val, bytes_ + start_, len);
-    start_ += len;
-    return true;
-  }
-}
-
-void ByteBuffer::WriteUInt8(uint8_t val) {
+void ByteBufferWriter::WriteUInt8(uint8_t val) {
   WriteBytes(reinterpret_cast<const char*>(&val), 1);
 }
 
-void ByteBuffer::WriteUInt16(uint16_t val) {
-  uint16_t v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork16(val) : val;
+void ByteBufferWriter::WriteUInt16(uint16_t val) {
+  uint16_t v = (Order() == ORDER_NETWORK) ? HostToNetwork16(val) : val;
   WriteBytes(reinterpret_cast<const char*>(&v), 2);
 }
 
-void ByteBuffer::WriteUInt24(uint32_t val) {
-  uint32_t v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork32(val) : val;
+void ByteBufferWriter::WriteUInt24(uint32_t val) {
+  uint32_t v = (Order() == ORDER_NETWORK) ? HostToNetwork32(val) : val;
   char* start = reinterpret_cast<char*>(&v);
-  if (byte_order_ == ORDER_NETWORK || IsHostBigEndian()) {
+  if (Order() == ORDER_NETWORK || IsHostBigEndian()) {
     ++start;
   }
   WriteBytes(start, 3);
 }
 
-void ByteBuffer::WriteUInt32(uint32_t val) {
-  uint32_t v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork32(val) : val;
+void ByteBufferWriter::WriteUInt32(uint32_t val) {
+  uint32_t v = (Order() == ORDER_NETWORK) ? HostToNetwork32(val) : val;
   WriteBytes(reinterpret_cast<const char*>(&v), 4);
 }
 
-void ByteBuffer::WriteUInt64(uint64_t val) {
-  uint64_t v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork64(val) : val;
+void ByteBufferWriter::WriteUInt64(uint64_t val) {
+  uint64_t v = (Order() == ORDER_NETWORK) ? HostToNetwork64(val) : val;
   WriteBytes(reinterpret_cast<const char*>(&v), 8);
 }
 
-void ByteBuffer::WriteString(const std::string& val) {
+void ByteBufferWriter::WriteString(const std::string& val) {
   WriteBytes(val.c_str(), val.size());
 }
 
-void ByteBuffer::WriteBytes(const char* val, size_t len) {
+void ByteBufferWriter::WriteBytes(const char* val, size_t len) {
   memcpy(ReserveWriteBuffer(len), val, len);
 }
 
-char* ByteBuffer::ReserveWriteBuffer(size_t len) {
+char* ByteBufferWriter::ReserveWriteBuffer(size_t len) {
   if (Length() + len > Capacity())
     Resize(Length() + len);
 
@@ -192,7 +105,7 @@
   return start;
 }
 
-void ByteBuffer::Resize(size_t size) {
+void ByteBufferWriter::Resize(size_t size) {
   size_t len = std::min(end_ - start_, size);
   if (size <= size_) {
     // Don't reallocate, just move data backwards
@@ -207,32 +120,133 @@
   }
   start_ = 0;
   end_ = len;
-  ++version_;
 }
 
-bool ByteBuffer::Consume(size_t size) {
+void ByteBufferWriter::Clear() {
+  memset(bytes_, 0, size_);
+  start_ = end_ = 0;
+}
+
+
+ByteBufferReader::ByteBufferReader(const char* bytes, size_t len)
+    : ByteBuffer(ORDER_NETWORK) {
+  Construct(bytes, len);
+}
+
+ByteBufferReader::ByteBufferReader(const char* bytes, size_t len,
+                                   ByteOrder byte_order)
+    : ByteBuffer(byte_order) {
+  Construct(bytes, len);
+}
+
+ByteBufferReader::ByteBufferReader(const char* bytes)
+    : ByteBuffer(ORDER_NETWORK) {
+  Construct(bytes, strlen(bytes));
+}
+
+ByteBufferReader::ByteBufferReader(const Buffer& buf)
+    : ByteBuffer(ORDER_NETWORK) {
+  Construct(buf.data<char>(), buf.size());
+}
+
+ByteBufferReader::ByteBufferReader(const ByteBufferWriter& buf)
+    : ByteBuffer(buf.Order()) {
+  Construct(buf.Data(), buf.Length());
+}
+
+void ByteBufferReader::Construct(const char* bytes, size_t len) {
+  bytes_ = bytes;
+  size_ = len;
+  start_ = 0;
+  end_ = len;
+}
+
+bool ByteBufferReader::ReadUInt8(uint8_t* val) {
+  if (!val) return false;
+
+  return ReadBytes(reinterpret_cast<char*>(val), 1);
+}
+
+bool ByteBufferReader::ReadUInt16(uint16_t* val) {
+  if (!val) return false;
+
+  uint16_t v;
+  if (!ReadBytes(reinterpret_cast<char*>(&v), 2)) {
+    return false;
+  } else {
+    *val = (Order() == ORDER_NETWORK) ? NetworkToHost16(v) : v;
+    return true;
+  }
+}
+
+bool ByteBufferReader::ReadUInt24(uint32_t* val) {
+  if (!val) return false;
+
+  uint32_t v = 0;
+  char* read_into = reinterpret_cast<char*>(&v);
+  if (Order() == ORDER_NETWORK || IsHostBigEndian()) {
+    ++read_into;
+  }
+
+  if (!ReadBytes(read_into, 3)) {
+    return false;
+  } else {
+    *val = (Order() == ORDER_NETWORK) ? NetworkToHost32(v) : v;
+    return true;
+  }
+}
+
+bool ByteBufferReader::ReadUInt32(uint32_t* val) {
+  if (!val) return false;
+
+  uint32_t v;
+  if (!ReadBytes(reinterpret_cast<char*>(&v), 4)) {
+    return false;
+  } else {
+    *val = (Order() == ORDER_NETWORK) ? NetworkToHost32(v) : v;
+    return true;
+  }
+}
+
+bool ByteBufferReader::ReadUInt64(uint64_t* val) {
+  if (!val) return false;
+
+  uint64_t v;
+  if (!ReadBytes(reinterpret_cast<char*>(&v), 8)) {
+    return false;
+  } else {
+    *val = (Order() == ORDER_NETWORK) ? NetworkToHost64(v) : v;
+    return true;
+  }
+}
+
+bool ByteBufferReader::ReadString(std::string* val, size_t len) {
+  if (!val) return false;
+
+  if (len > Length()) {
+    return false;
+  } else {
+    val->append(bytes_ + start_, len);
+    start_ += len;
+    return true;
+  }
+}
+
+bool ByteBufferReader::ReadBytes(char* val, size_t len) {
+  if (len > Length()) {
+    return false;
+  } else {
+    memcpy(val, bytes_ + start_, len);
+    start_ += len;
+    return true;
+  }
+}
+
+bool ByteBufferReader::Consume(size_t size) {
   if (size > Length())
     return false;
   start_ += size;
   return true;
 }
 
-ByteBuffer::ReadPosition ByteBuffer::GetReadPosition() const {
-  return ReadPosition(start_, version_);
-}
-
-bool ByteBuffer::SetReadPosition(const ReadPosition &position) {
-  if (position.version_ != version_) {
-    return false;
-  }
-  start_ = position.start_;
-  return true;
-}
-
-void ByteBuffer::Clear() {
-  memset(bytes_, 0, size_);
-  start_ = end_ = 0;
-  ++version_;
-}
-
 }  // namespace rtc
diff --git a/webrtc/base/bytebuffer.h b/webrtc/base/bytebuffer.h
index ad2e552..8fd0863 100644
--- a/webrtc/base/bytebuffer.h
+++ b/webrtc/base/bytebuffer.h
@@ -21,29 +21,87 @@
 
 class ByteBuffer {
  public:
-
   enum ByteOrder {
     ORDER_NETWORK = 0,  // Default, use network byte order (big endian).
     ORDER_HOST,         // Use the native order of the host.
   };
 
+  explicit ByteBuffer(ByteOrder byte_order) : byte_order_(byte_order) {}
+
+  ByteOrder Order() const { return byte_order_; }
+
+ private:
+  ByteOrder byte_order_;
+
+  RTC_DISALLOW_COPY_AND_ASSIGN(ByteBuffer);
+};
+
+class ByteBufferWriter : public ByteBuffer {
+ public:
   // |byte_order| defines order of bytes in the buffer.
-  ByteBuffer();
-  explicit ByteBuffer(ByteOrder byte_order);
-  ByteBuffer(const char* bytes, size_t len);
-  ByteBuffer(const char* bytes, size_t len, ByteOrder byte_order);
+  ByteBufferWriter();
+  explicit ByteBufferWriter(ByteOrder byte_order);
+  ByteBufferWriter(const char* bytes, size_t len);
+  ByteBufferWriter(const char* bytes, size_t len, ByteOrder byte_order);
 
-  // Initializes buffer from a zero-terminated string.
-  explicit ByteBuffer(const char* bytes);
-
-  explicit ByteBuffer(const Buffer& buf);
-
-  ~ByteBuffer();
+  ~ByteBufferWriter();
 
   const char* Data() const { return bytes_ + start_; }
   size_t Length() const { return end_ - start_; }
   size_t Capacity() const { return size_ - start_; }
-  ByteOrder Order() const { return byte_order_; }
+
+  // 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 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 start_;
+  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);
+};
+
+// The ByteBufferReader references the passed data, i.e. the pointer must be
+// valid during the lifetime of the reader.
+class ByteBufferReader : public ByteBuffer {
+ public:
+  ByteBufferReader(const char* bytes, size_t len);
+  ByteBufferReader(const char* bytes, size_t len, ByteOrder byte_order);
+
+  // Initializes buffer from a zero-terminated string.
+  explicit ByteBufferReader(const char* bytes);
+
+  explicit ByteBufferReader(const Buffer& buf);
+
+  explicit ByteBufferReader(const ByteBufferWriter& buf);
+
+  // Returns start of unprocessed data.
+  const char* Data() const { return bytes_ + start_; }
+  // Returns number of unprocessed bytes.
+  size_t Length() const { return end_ - start_; }
 
   // Read a next value from the buffer. Return false if there isn't
   // enough data left for the specified type.
@@ -58,63 +116,21 @@
   // if there is less than |len| bytes left.
   bool ReadString(std::string* val, size_t len);
 
-  // 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 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
-  // ByteBuffer.
-  char* ReserveWriteBuffer(size_t len);
-
-  // Resize the buffer to the specified |size|. This invalidates any remembered
-  // seek positions.
-  void Resize(size_t size);
-
   // Moves current position |size| bytes forward. Returns false if
   // there is less than |size| bytes left in the buffer. Consume doesn't
   // permanently remove data, so remembered read positions are still valid
   // after this call.
   bool Consume(size_t size);
 
-  // Clears the contents of the buffer. After this, Length() will be 0.
-  void Clear();
-
-  // Used with GetReadPosition/SetReadPosition.
-  class ReadPosition {
-    friend class ByteBuffer;
-    ReadPosition(size_t start, int version)
-        : start_(start), version_(version) { }
-    size_t start_;
-    int version_;
-  };
-
-  // Remembers the current read position for a future SetReadPosition. Any
-  // calls to Shift or Resize in the interim will invalidate the position.
-  ReadPosition GetReadPosition() const;
-
-  // If the given position is still valid, restores that read position.
-  bool SetReadPosition(const ReadPosition &position);
-
  private:
-  void Construct(const char* bytes, size_t size, ByteOrder byte_order);
+  void Construct(const char* bytes, size_t size);
 
-  char* bytes_;
+  const char* bytes_;
   size_t size_;
   size_t start_;
   size_t end_;
-  int version_;
-  ByteOrder byte_order_;
 
-  // There are sensible ways to define these, but they aren't needed in our code
-  // base.
-  RTC_DISALLOW_COPY_AND_ASSIGN(ByteBuffer);
+  RTC_DISALLOW_COPY_AND_ASSIGN(ByteBufferReader);
 };
 
 }  // namespace rtc
diff --git a/webrtc/base/bytebuffer_unittest.cc b/webrtc/base/bytebuffer_unittest.cc
index 0287d85..7236418 100644
--- a/webrtc/base/bytebuffer_unittest.cc
+++ b/webrtc/base/bytebuffer_unittest.cc
@@ -54,7 +54,7 @@
 }
 
 TEST(ByteBufferTest, TestBufferLength) {
-  ByteBuffer buffer;
+  ByteBufferWriter buffer;
   size_t size = 0;
   EXPECT_EQ(size, buffer.Length());
 
@@ -77,117 +77,102 @@
   buffer.WriteUInt64(1);
   size += 8;
   EXPECT_EQ(size, buffer.Length());
-
-  EXPECT_TRUE(buffer.Consume(0));
-  EXPECT_EQ(size, buffer.Length());
-
-  EXPECT_TRUE(buffer.Consume(4));
-  size -= 4;
-  EXPECT_EQ(size, buffer.Length());
-}
-
-TEST(ByteBufferTest, TestGetSetReadPosition) {
-  ByteBuffer buffer("ABCDEF", 6);
-  EXPECT_EQ(6U, buffer.Length());
-  ByteBuffer::ReadPosition pos(buffer.GetReadPosition());
-  EXPECT_TRUE(buffer.SetReadPosition(pos));
-  EXPECT_EQ(6U, buffer.Length());
-  std::string read;
-  EXPECT_TRUE(buffer.ReadString(&read, 3));
-  EXPECT_EQ("ABC", read);
-  EXPECT_EQ(3U, buffer.Length());
-  EXPECT_TRUE(buffer.SetReadPosition(pos));
-  EXPECT_EQ(6U, buffer.Length());
-  read.clear();
-  EXPECT_TRUE(buffer.ReadString(&read, 3));
-  EXPECT_EQ("ABC", read);
-  EXPECT_EQ(3U, buffer.Length());
-  // For a resize by writing Capacity() number of bytes.
-  size_t capacity = buffer.Capacity();
-  buffer.ReserveWriteBuffer(buffer.Capacity());
-  EXPECT_EQ(capacity + 3U, buffer.Length());
-  EXPECT_FALSE(buffer.SetReadPosition(pos));
-  read.clear();
-  EXPECT_TRUE(buffer.ReadString(&read, 3));
-  EXPECT_EQ("DEF", read);
 }
 
 TEST(ByteBufferTest, TestReadWriteBuffer) {
-  ByteBuffer::ByteOrder orders[2] = { ByteBuffer::ORDER_HOST,
-                                      ByteBuffer::ORDER_NETWORK };
+  ByteBufferWriter::ByteOrder orders[2] = { ByteBufferWriter::ORDER_HOST,
+                                            ByteBufferWriter::ORDER_NETWORK };
   for (size_t i = 0; i < arraysize(orders); i++) {
-    ByteBuffer buffer(orders[i]);
+    ByteBufferWriter buffer(orders[i]);
     EXPECT_EQ(orders[i], buffer.Order());
+    ByteBufferReader read_buf(nullptr, 0, orders[i]);
+    EXPECT_EQ(orders[i], read_buf.Order());
     uint8_t ru8;
-    EXPECT_FALSE(buffer.ReadUInt8(&ru8));
+    EXPECT_FALSE(read_buf.ReadUInt8(&ru8));
 
     // Write and read uint8_t.
     uint8_t wu8 = 1;
     buffer.WriteUInt8(wu8);
-    EXPECT_TRUE(buffer.ReadUInt8(&ru8));
+    ByteBufferReader read_buf1(buffer.Data(), buffer.Length(), orders[i]);
+    EXPECT_TRUE(read_buf1.ReadUInt8(&ru8));
     EXPECT_EQ(wu8, ru8);
-    EXPECT_EQ(0U, buffer.Length());
+    EXPECT_EQ(0U, read_buf1.Length());
+    buffer.Clear();
 
     // Write and read uint16_t.
     uint16_t wu16 = (1 << 8) + 1;
     buffer.WriteUInt16(wu16);
+    ByteBufferReader read_buf2(buffer.Data(), buffer.Length(), orders[i]);
     uint16_t ru16;
-    EXPECT_TRUE(buffer.ReadUInt16(&ru16));
+    EXPECT_TRUE(read_buf2.ReadUInt16(&ru16));
     EXPECT_EQ(wu16, ru16);
-    EXPECT_EQ(0U, buffer.Length());
+    EXPECT_EQ(0U, read_buf2.Length());
+    buffer.Clear();
 
     // Write and read uint24.
     uint32_t wu24 = (3 << 16) + (2 << 8) + 1;
     buffer.WriteUInt24(wu24);
+    ByteBufferReader read_buf3(buffer.Data(), buffer.Length(), orders[i]);
     uint32_t ru24;
-    EXPECT_TRUE(buffer.ReadUInt24(&ru24));
+    EXPECT_TRUE(read_buf3.ReadUInt24(&ru24));
     EXPECT_EQ(wu24, ru24);
-    EXPECT_EQ(0U, buffer.Length());
+    EXPECT_EQ(0U, read_buf3.Length());
+    buffer.Clear();
 
     // Write and read uint32_t.
     uint32_t wu32 = (4 << 24) + (3 << 16) + (2 << 8) + 1;
     buffer.WriteUInt32(wu32);
+    ByteBufferReader read_buf4(buffer.Data(), buffer.Length(), orders[i]);
     uint32_t ru32;
-    EXPECT_TRUE(buffer.ReadUInt32(&ru32));
+    EXPECT_TRUE(read_buf4.ReadUInt32(&ru32));
     EXPECT_EQ(wu32, ru32);
-    EXPECT_EQ(0U, buffer.Length());
+    EXPECT_EQ(0U, read_buf3.Length());
+    buffer.Clear();
 
     // Write and read uint64_t.
     uint32_t another32 = (8 << 24) + (7 << 16) + (6 << 8) + 5;
     uint64_t wu64 = (static_cast<uint64_t>(another32) << 32) + wu32;
     buffer.WriteUInt64(wu64);
+    ByteBufferReader read_buf5(buffer.Data(), buffer.Length(), orders[i]);
     uint64_t ru64;
-    EXPECT_TRUE(buffer.ReadUInt64(&ru64));
+    EXPECT_TRUE(read_buf5.ReadUInt64(&ru64));
     EXPECT_EQ(wu64, ru64);
-    EXPECT_EQ(0U, buffer.Length());
+    EXPECT_EQ(0U, read_buf5.Length());
+    buffer.Clear();
 
     // Write and read string.
     std::string write_string("hello");
     buffer.WriteString(write_string);
+    ByteBufferReader read_buf6(buffer.Data(), buffer.Length(), orders[i]);
     std::string read_string;
-    EXPECT_TRUE(buffer.ReadString(&read_string, write_string.size()));
+    EXPECT_TRUE(read_buf6.ReadString(&read_string, write_string.size()));
     EXPECT_EQ(write_string, read_string);
-    EXPECT_EQ(0U, buffer.Length());
+    EXPECT_EQ(0U, read_buf6.Length());
+    buffer.Clear();
 
     // Write and read bytes
     char write_bytes[] = "foo";
     buffer.WriteBytes(write_bytes, 3);
+    ByteBufferReader read_buf7(buffer.Data(), buffer.Length(), orders[i]);
     char read_bytes[3];
-    EXPECT_TRUE(buffer.ReadBytes(read_bytes, 3));
+    EXPECT_TRUE(read_buf7.ReadBytes(read_bytes, 3));
     for (int i = 0; i < 3; ++i) {
       EXPECT_EQ(write_bytes[i], read_bytes[i]);
     }
-    EXPECT_EQ(0U, buffer.Length());
+    EXPECT_EQ(0U, read_buf7.Length());
+    buffer.Clear();
 
     // Write and read reserved buffer space
     char* write_dst = buffer.ReserveWriteBuffer(3);
     memcpy(write_dst, write_bytes, 3);
+    ByteBufferReader read_buf8(buffer.Data(), buffer.Length(), orders[i]);
     memset(read_bytes, 0, 3);
-    EXPECT_TRUE(buffer.ReadBytes(read_bytes, 3));
+    EXPECT_TRUE(read_buf8.ReadBytes(read_bytes, 3));
     for (int i = 0; i < 3; ++i) {
       EXPECT_EQ(write_bytes[i], read_bytes[i]);
     }
-    EXPECT_EQ(0U, buffer.Length());
+    EXPECT_EQ(0U, read_buf8.Length());
+    buffer.Clear();
 
     // Write and read in order.
     buffer.WriteUInt8(wu8);
@@ -195,17 +180,19 @@
     buffer.WriteUInt24(wu24);
     buffer.WriteUInt32(wu32);
     buffer.WriteUInt64(wu64);
-    EXPECT_TRUE(buffer.ReadUInt8(&ru8));
+    ByteBufferReader read_buf9(buffer.Data(), buffer.Length(), orders[i]);
+    EXPECT_TRUE(read_buf9.ReadUInt8(&ru8));
     EXPECT_EQ(wu8, ru8);
-    EXPECT_TRUE(buffer.ReadUInt16(&ru16));
+    EXPECT_TRUE(read_buf9.ReadUInt16(&ru16));
     EXPECT_EQ(wu16, ru16);
-    EXPECT_TRUE(buffer.ReadUInt24(&ru24));
+    EXPECT_TRUE(read_buf9.ReadUInt24(&ru24));
     EXPECT_EQ(wu24, ru24);
-    EXPECT_TRUE(buffer.ReadUInt32(&ru32));
+    EXPECT_TRUE(read_buf9.ReadUInt32(&ru32));
     EXPECT_EQ(wu32, ru32);
-    EXPECT_TRUE(buffer.ReadUInt64(&ru64));
+    EXPECT_TRUE(read_buf9.ReadUInt64(&ru64));
     EXPECT_EQ(wu64, ru64);
-    EXPECT_EQ(0U, buffer.Length());
+    EXPECT_EQ(0U, read_buf9.Length());
+    buffer.Clear();
   }
 }
 
diff --git a/webrtc/base/socketadapters.cc b/webrtc/base/socketadapters.cc
index 2b513dc..85c1267 100644
--- a/webrtc/base/socketadapters.cc
+++ b/webrtc/base/socketadapters.cc
@@ -561,7 +561,7 @@
 void AsyncSocksProxySocket::ProcessInput(char* data, size_t* len) {
   ASSERT(state_ < SS_TUNNEL);
 
-  ByteBuffer response(data, *len);
+  ByteBufferReader response(data, *len);
 
   if (state_ == SS_HELLO) {
     uint8_t ver, method;
@@ -638,7 +638,7 @@
 
   // Consume parsed data
   *len = response.Length();
-  memcpy(data, response.Data(), *len);
+  memmove(data, response.Data(), *len);
 
   if (state_ != SS_TUNNEL)
     return;
@@ -653,7 +653,7 @@
 }
 
 void AsyncSocksProxySocket::SendHello() {
-  ByteBuffer request;
+  ByteBufferWriter request;
   request.WriteUInt8(5);    // Socks Version
   if (user_.empty()) {
     request.WriteUInt8(1);  // Authentication Mechanisms
@@ -668,7 +668,7 @@
 }
 
 void AsyncSocksProxySocket::SendAuth() {
-  ByteBuffer request;
+  ByteBufferWriter request;
   request.WriteUInt8(1);           // Negotiation Version
   request.WriteUInt8(static_cast<uint8_t>(user_.size()));
   request.WriteString(user_);      // Username
@@ -684,7 +684,7 @@
 }
 
 void AsyncSocksProxySocket::SendConnect() {
-  ByteBuffer request;
+  ByteBufferWriter request;
   request.WriteUInt8(5);              // Socks Version
   request.WriteUInt8(1);              // CONNECT
   request.WriteUInt8(0);              // Reserved
@@ -719,7 +719,7 @@
   // TODO: See if the whole message has arrived
   ASSERT(state_ < SS_CONNECT_PENDING);
 
-  ByteBuffer response(data, *len);
+  ByteBufferReader response(data, *len);
   if (state_ == SS_HELLO) {
     HandleHello(&response);
   } else if (state_ == SS_AUTH) {
@@ -730,14 +730,14 @@
 
   // Consume parsed data
   *len = response.Length();
-  memcpy(data, response.Data(), *len);
+  memmove(data, response.Data(), *len);
 }
 
-void AsyncSocksProxyServerSocket::DirectSend(const ByteBuffer& buf) {
+void AsyncSocksProxyServerSocket::DirectSend(const ByteBufferWriter& buf) {
   BufferedReadAdapter::DirectSend(buf.Data(), buf.Length());
 }
 
-void AsyncSocksProxyServerSocket::HandleHello(ByteBuffer* request) {
+void AsyncSocksProxyServerSocket::HandleHello(ByteBufferReader* request) {
   uint8_t ver, num_methods;
   if (!request->ReadUInt8(&ver) ||
       !request->ReadUInt8(&num_methods)) {
@@ -769,13 +769,13 @@
 }
 
 void AsyncSocksProxyServerSocket::SendHelloReply(uint8_t method) {
-  ByteBuffer response;
+  ByteBufferWriter response;
   response.WriteUInt8(5);  // Socks Version
   response.WriteUInt8(method);  // Auth method
   DirectSend(response);
 }
 
-void AsyncSocksProxyServerSocket::HandleAuth(ByteBuffer* request) {
+void AsyncSocksProxyServerSocket::HandleAuth(ByteBufferReader* request) {
   uint8_t ver, user_len, pass_len;
   std::string user, pass;
   if (!request->ReadUInt8(&ver) ||
@@ -793,13 +793,13 @@
 }
 
 void AsyncSocksProxyServerSocket::SendAuthReply(uint8_t result) {
-  ByteBuffer response;
+  ByteBufferWriter response;
   response.WriteUInt8(1);  // Negotiation Version
   response.WriteUInt8(result);
   DirectSend(response);
 }
 
-void AsyncSocksProxyServerSocket::HandleConnect(ByteBuffer* request) {
+void AsyncSocksProxyServerSocket::HandleConnect(ByteBufferReader* request) {
   uint8_t ver, command, reserved, addr_type;
   uint32_t ip;
   uint16_t port;
@@ -828,7 +828,7 @@
   if (state_ != SS_CONNECT_PENDING)
     return;
 
-  ByteBuffer response;
+  ByteBufferWriter response;
   response.WriteUInt8(5);  // Socks version
   response.WriteUInt8((result != 0));  // 0x01 is generic error
   response.WriteUInt8(0);  // reserved
diff --git a/webrtc/base/socketadapters.h b/webrtc/base/socketadapters.h
index ece591d..ae0ed9a 100644
--- a/webrtc/base/socketadapters.h
+++ b/webrtc/base/socketadapters.h
@@ -21,7 +21,8 @@
 namespace rtc {
 
 struct HttpAuthContext;
-class ByteBuffer;
+class ByteBufferReader;
+class ByteBufferWriter;
 
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -193,13 +194,13 @@
 
  private:
   void ProcessInput(char* data, size_t* len) override;
-  void DirectSend(const ByteBuffer& buf);
+  void DirectSend(const ByteBufferWriter& buf);
 
-  void HandleHello(ByteBuffer* request);
+  void HandleHello(ByteBufferReader* request);
   void SendHelloReply(uint8_t method);
-  void HandleAuth(ByteBuffer* request);
+  void HandleAuth(ByteBufferReader* request);
   void SendAuthReply(uint8_t result);
-  void HandleConnect(ByteBuffer* request);
+  void HandleConnect(ByteBufferReader* request);
   void SendConnectResult(int result, const SocketAddress& addr) override;
 
   void Error(int error);
diff --git a/webrtc/libjingle/xmpp/xmppsocket.cc b/webrtc/libjingle/xmpp/xmppsocket.cc
index fd07828..9c1bf8b 100644
--- a/webrtc/libjingle/xmpp/xmppsocket.cc
+++ b/webrtc/libjingle/xmpp/xmppsocket.cc
@@ -77,10 +77,13 @@
 
 void XmppSocket::OnWriteEvent(rtc::AsyncSocket * socket) {
   // Write bytes if there are any
-  while (buffer_.Length() != 0) {
-    int written = cricket_socket_->Send(buffer_.Data(), buffer_.Length());
+  while (buffer_.size() > 0) {
+    int written = cricket_socket_->Send(buffer_.data(), buffer_.size());
     if (written > 0) {
-      buffer_.Consume(written);
+      ASSERT(static_cast<size_t>(written) <= buffer_.size());
+      memmove(buffer_.data(), buffer_.data() + written,
+          buffer_.size() - written);
+      buffer_.SetSize(buffer_.size() - written);
       continue;
     }
     if (!cricket_socket_->IsBlocking())
@@ -127,11 +130,11 @@
     SignalRead();
   if ((events & rtc::SE_WRITE)) {
     // Write bytes if there are any
-    while (buffer_.Length() != 0) {
+    while (buffer_.size() > 0) {
       rtc::StreamResult result;
       size_t written;
       int error;
-      result = stream_->Write(buffer_.Data(), buffer_.Length(),
+      result = stream_->Write(buffer_.data(), buffer_.size(),
                               &written, &error);
       if (result == rtc::SR_ERROR) {
         LOG(LS_ERROR) << "Send error: " << error;
@@ -141,7 +144,10 @@
         return;
       ASSERT(result == rtc::SR_SUCCESS);
       ASSERT(written > 0);
-      buffer_.Shift(written);
+      ASSERT(written <= buffer_.size());
+      memmove(buffer_.data(), buffer_.data() + written,
+          buffer_.size() - written);
+      buffer_.SetSize(buffer_.size() - written);
     }
   }
   if ((events & rtc::SE_CLOSE))
@@ -187,7 +193,7 @@
 }
 
 bool XmppSocket::Write(const char * data, size_t len) {
-  buffer_.WriteBytes(data, len);
+  buffer_.AppendData(data, len);
 #ifndef USE_SSLSTREAM
   OnWriteEvent(cricket_socket_);
 #else  // USE_SSLSTREAM
diff --git a/webrtc/libjingle/xmpp/xmppsocket.h b/webrtc/libjingle/xmpp/xmppsocket.h
index 527b23a..d862afd 100644
--- a/webrtc/libjingle/xmpp/xmppsocket.h
+++ b/webrtc/libjingle/xmpp/xmppsocket.h
@@ -14,7 +14,7 @@
 #include "webrtc/libjingle/xmpp/asyncsocket.h"
 #include "webrtc/libjingle/xmpp/xmppengine.h"
 #include "webrtc/base/asyncsocket.h"
-#include "webrtc/base/bytebuffer.h"
+#include "webrtc/base/buffer.h"
 #include "webrtc/base/sigslot.h"
 
 // The below define selects the SSLStreamAdapter implementation for
@@ -62,7 +62,7 @@
   rtc::StreamInterface *stream_;
 #endif  // USE_SSLSTREAM
   buzz::AsyncSocket::State state_;
-  rtc::ByteBuffer buffer_;
+  rtc::Buffer buffer_;
   buzz::TlsOptions tls_;
 };
 
diff --git a/webrtc/media/base/rtpdump.cc b/webrtc/media/base/rtpdump.cc
index 0cacac7..a109f2d 100644
--- a/webrtc/media/base/rtpdump.cc
+++ b/webrtc/media/base/rtpdump.cc
@@ -36,7 +36,7 @@
       padding(0) {
 }
 
-void RtpDumpFileHeader::WriteToByteBuffer(rtc::ByteBuffer* buf) {
+void RtpDumpFileHeader::WriteToByteBuffer(rtc::ByteBufferWriter* buf) {
   buf->WriteUInt32(start_sec);
   buf->WriteUInt32(start_usec);
   buf->WriteUInt32(source);
@@ -113,7 +113,7 @@
   if (res != rtc::SR_SUCCESS) {
     return res;
   }
-  rtc::ByteBuffer buf(header, sizeof(header));
+  rtc::ByteBufferReader buf(header, sizeof(header));
   uint16_t dump_packet_len;
   uint16_t data_len;
   // Read the full length of the rtpdump packet, including the rtpdump header.
@@ -157,7 +157,7 @@
   char header[RtpDumpFileHeader::kHeaderLength];
   res = stream_->ReadAll(header, sizeof(header), NULL, NULL);
   if (res == rtc::SR_SUCCESS) {
-    rtc::ByteBuffer buf(header, sizeof(header));
+    rtc::ByteBufferReader buf(header, sizeof(header));
     uint32_t start_sec;
     uint32_t start_usec;
     buf.ReadUInt32(&start_sec);
@@ -290,7 +290,7 @@
     sequence += loop_count_ * rtp_seq_num_increase_;
     timestamp += loop_count_ * rtp_timestamp_increase_;
     // Write the updated sequence number and timestamp back to the RTP packet.
-    rtc::ByteBuffer buffer;
+    rtc::ByteBufferWriter buffer;
     buffer.WriteUInt16(sequence);
     buffer.WriteUInt32(timestamp);
     memcpy(&packet->data[2], buffer.Data(), buffer.Length());
@@ -326,7 +326,7 @@
     return res;
   }
 
-  rtc::ByteBuffer buf;
+  rtc::ByteBufferWriter buf;
   RtpDumpFileHeader file_header(rtc::Time(), 0, 0);
   file_header.WriteToByteBuffer(&buf);
   return WriteToStream(buf.Data(), buf.Length());
@@ -355,7 +355,7 @@
   }
 
   // Write the dump packet header.
-  rtc::ByteBuffer buf;
+  rtc::ByteBufferWriter buf;
   buf.WriteUInt16(
       static_cast<uint16_t>(RtpDumpPacket::kHeaderLength + write_len));
   buf.WriteUInt16(static_cast<uint16_t>(rtcp ? 0 : data_len));
diff --git a/webrtc/media/base/rtpdump.h b/webrtc/media/base/rtpdump.h
index 64880c7..4ce4792 100644
--- a/webrtc/media/base/rtpdump.h
+++ b/webrtc/media/base/rtpdump.h
@@ -40,7 +40,7 @@
 
 struct RtpDumpFileHeader {
   RtpDumpFileHeader(uint32_t start_ms, uint32_t s, uint16_t p);
-  void WriteToByteBuffer(rtc::ByteBuffer* buf);
+  void WriteToByteBuffer(rtc::ByteBufferWriter* buf);
 
   static const char kFirstLine[];
   static const size_t kHeaderLength = 16;
diff --git a/webrtc/media/base/rtpdump_unittest.cc b/webrtc/media/base/rtpdump_unittest.cc
index a5b79c9..748ceab 100644
--- a/webrtc/media/base/rtpdump_unittest.cc
+++ b/webrtc/media/base/rtpdump_unittest.cc
@@ -24,7 +24,7 @@
 
 // Test that we read the correct header fields from the RTP/RTCP packet.
 TEST(RtpDumpTest, ReadRtpDumpPacket) {
-  rtc::ByteBuffer rtp_buf;
+  rtc::ByteBufferWriter rtp_buf;
   RtpTestUtility::kTestRawRtpPackets[0].WriteToByteBuffer(kTestSsrc, &rtp_buf);
   RtpDumpPacket rtp_packet(rtp_buf.Data(), rtp_buf.Length(), 0, false);
 
@@ -46,7 +46,7 @@
   EXPECT_EQ(kTestSsrc, ssrc);
   EXPECT_FALSE(rtp_packet.GetRtcpType(&rtcp_type));
 
-  rtc::ByteBuffer rtcp_buf;
+  rtc::ByteBufferWriter rtcp_buf;
   RtpTestUtility::kTestRawRtcpPackets[0].WriteToByteBuffer(&rtcp_buf);
   RtpDumpPacket rtcp_packet(rtcp_buf.Data(), rtcp_buf.Length(), 0, true);
 
diff --git a/webrtc/media/base/testutils.cc b/webrtc/media/base/testutils.cc
index 33d0a97..ec3828c 100644
--- a/webrtc/media/base/testutils.cc
+++ b/webrtc/media/base/testutils.cc
@@ -32,7 +32,7 @@
 // Implementation of RawRtpPacket
 /////////////////////////////////////////////////////////////////////////
 void RawRtpPacket::WriteToByteBuffer(uint32_t in_ssrc,
-                                     rtc::ByteBuffer* buf) const {
+                                     rtc::ByteBufferWriter* buf) const {
   if (!buf) return;
 
   buf->WriteUInt8(ver_to_cc);
@@ -43,7 +43,7 @@
   buf->WriteBytes(payload, sizeof(payload));
 }
 
-bool RawRtpPacket::ReadFromByteBuffer(rtc::ByteBuffer* buf) {
+bool RawRtpPacket::ReadFromByteBuffer(rtc::ByteBufferReader* buf) {
   if (!buf) return false;
 
   bool ret = true;
@@ -71,7 +71,7 @@
 /////////////////////////////////////////////////////////////////////////
 // Implementation of RawRtcpPacket
 /////////////////////////////////////////////////////////////////////////
-void RawRtcpPacket::WriteToByteBuffer(rtc::ByteBuffer *buf) const {
+void RawRtcpPacket::WriteToByteBuffer(rtc::ByteBufferWriter *buf) const {
   if (!buf) return;
 
   buf->WriteUInt8(ver_to_count);
@@ -80,7 +80,7 @@
   buf->WriteBytes(payload, sizeof(payload));
 }
 
-bool RawRtcpPacket::ReadFromByteBuffer(rtc::ByteBuffer* buf) {
+bool RawRtcpPacket::ReadFromByteBuffer(rtc::ByteBufferReader* buf) {
   if (!buf) return false;
 
   bool ret = true;
@@ -129,7 +129,7 @@
   bool result = true;
   uint32_t elapsed_time_ms = 0;
   for (size_t i = 0; i < count && result; ++i) {
-    rtc::ByteBuffer buf;
+    rtc::ByteBufferWriter buf;
     if (rtcp) {
       kTestRawRtcpPackets[i].WriteToByteBuffer(&buf);
     } else {
@@ -164,7 +164,7 @@
     prev_elapsed_time = packet.elapsed_time;
 
     // Check the RTP or RTCP packet.
-    rtc::ByteBuffer buf(reinterpret_cast<const char*>(&packet.data[0]),
+    rtc::ByteBufferReader buf(reinterpret_cast<const char*>(&packet.data[0]),
                               packet.data.size());
     if (packet.is_rtcp()) {
       // RTCP packet.
@@ -194,7 +194,7 @@
                                   bool header_only) {
   if (!dump || !raw) return false;
 
-  rtc::ByteBuffer buf;
+  rtc::ByteBufferWriter buf;
   raw->WriteToByteBuffer(RtpTestUtility::kDefaultSsrc, &buf);
 
   if (header_only) {
diff --git a/webrtc/media/base/testutils.h b/webrtc/media/base/testutils.h
index ba64f82..6d814ef 100644
--- a/webrtc/media/base/testutils.h
+++ b/webrtc/media/base/testutils.h
@@ -24,7 +24,8 @@
 #include "webrtc/media/base/videocommon.h"
 
 namespace rtc {
-class ByteBuffer;
+class ByteBufferReader;
+class ByteBufferWriter;
 class StreamInterface;
 }
 
@@ -45,8 +46,8 @@
 class VideoFrame;
 
 struct RawRtpPacket {
-  void WriteToByteBuffer(uint32_t in_ssrc, rtc::ByteBuffer* buf) const;
-  bool ReadFromByteBuffer(rtc::ByteBuffer* buf);
+  void WriteToByteBuffer(uint32_t in_ssrc, rtc::ByteBufferWriter* buf) const;
+  bool ReadFromByteBuffer(rtc::ByteBufferReader* buf);
   // Check if this packet is the same as the specified packet except the
   // sequence number and timestamp, which should be the same as the specified
   // parameters.
@@ -65,8 +66,8 @@
 };
 
 struct RawRtcpPacket {
-  void WriteToByteBuffer(rtc::ByteBuffer* buf) const;
-  bool ReadFromByteBuffer(rtc::ByteBuffer* buf);
+  void WriteToByteBuffer(rtc::ByteBufferWriter* buf) const;
+  bool ReadFromByteBuffer(rtc::ByteBufferReader* buf);
   bool EqualsTo(const RawRtcpPacket& packet) const;
 
   uint8_t ver_to_count;
diff --git a/webrtc/media/base/videoengine_unittest.h b/webrtc/media/base/videoengine_unittest.h
index 929c948..01a4f76 100644
--- a/webrtc/media/base/videoengine_unittest.h
+++ b/webrtc/media/base/videoengine_unittest.h
@@ -279,8 +279,7 @@
                              uint32_t* tstamp,
                              uint32_t* ssrc,
                              std::string* payload) {
-    // TODO(jbauch): avoid copying the buffer data into the ByteBuffer
-    rtc::ByteBuffer buf(p->data<char>(), p->size());
+    rtc::ByteBufferReader buf(p->data<char>(), p->size());
     uint8_t u08 = 0;
     uint16_t u16 = 0;
     uint32_t u32 = 0;
@@ -340,8 +339,7 @@
     int count = 0;
     for (int i = start_index; i < stop_index; ++i) {
       std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtcpPacket(i));
-      // TODO(jbauch): avoid copying the buffer data into the ByteBuffer
-      rtc::ByteBuffer buf(p->data<char>(), p->size());
+      rtc::ByteBufferReader buf(p->data<char>(), p->size());
       size_t total_len = 0;
       // The packet may be a compound RTCP packet.
       while (total_len < p->size()) {
diff --git a/webrtc/modules/rtp_rtcp/source/h264_bitstream_parser.cc b/webrtc/modules/rtp_rtcp/source/h264_bitstream_parser.cc
index b78b96d..6d8b407 100644
--- a/webrtc/modules/rtp_rtcp/source/h264_bitstream_parser.cc
+++ b/webrtc/modules/rtp_rtcp/source/h264_bitstream_parser.cc
@@ -68,9 +68,9 @@
 // TODO(pbos): Make parsing RBSP something that can be integrated into BitBuffer
 // so we don't have to copy the entire frames when only interested in the
 // headers.
-rtc::ByteBuffer* ParseRbsp(const uint8_t* bytes, size_t length) {
+rtc::ByteBufferWriter* ParseRbsp(const uint8_t* bytes, size_t length) {
   // Copied from webrtc::H264SpsParser::Parse.
-  rtc::ByteBuffer* rbsp_buffer = new rtc::ByteBuffer;
+  rtc::ByteBufferWriter* rbsp_buffer = new rtc::ByteBufferWriter();
   for (size_t i = 0; i < length;) {
     if (length - i >= 3 && bytes[i] == 0 && bytes[i + 1] == 0 &&
         bytes[i + 2] == 3) {
@@ -103,7 +103,7 @@
   sps_parsed_ = false;
   // Parse out the SPS RBSP. It should be small, so it's ok that we create a
   // copy. We'll eventually write this back.
-  rtc::scoped_ptr<rtc::ByteBuffer> sps_rbsp(
+  rtc::scoped_ptr<rtc::ByteBufferWriter> sps_rbsp(
       ParseRbsp(sps + kNaluHeaderAndTypeSize, length - kNaluHeaderAndTypeSize));
   rtc::BitBuffer sps_parser(reinterpret_cast<const uint8_t*>(sps_rbsp->Data()),
                             sps_rbsp->Length());
@@ -209,7 +209,7 @@
   // We're starting a new stream, so reset picture type rewriting values.
   pps_ = PpsState();
   pps_parsed_ = false;
-  rtc::scoped_ptr<rtc::ByteBuffer> buffer(
+  rtc::scoped_ptr<rtc::ByteBufferWriter> buffer(
       ParseRbsp(pps + kNaluHeaderAndTypeSize, length - kNaluHeaderAndTypeSize));
   rtc::BitBuffer parser(reinterpret_cast<const uint8_t*>(buffer->Data()),
                         buffer->Length());
@@ -317,7 +317,7 @@
   RTC_CHECK(sps_parsed_);
   RTC_CHECK(pps_parsed_);
   last_slice_qp_delta_parsed_ = false;
-  rtc::scoped_ptr<rtc::ByteBuffer> slice_rbsp(ParseRbsp(
+  rtc::scoped_ptr<rtc::ByteBufferWriter> slice_rbsp(ParseRbsp(
       source + kNaluHeaderAndTypeSize, source_length - kNaluHeaderAndTypeSize));
   rtc::BitBuffer slice_reader(
       reinterpret_cast<const uint8_t*>(slice_rbsp->Data()),
diff --git a/webrtc/modules/rtp_rtcp/source/h264_sps_parser.cc b/webrtc/modules/rtp_rtcp/source/h264_sps_parser.cc
index 2fb723e..904a9e2 100644
--- a/webrtc/modules/rtp_rtcp/source/h264_sps_parser.cc
+++ b/webrtc/modules/rtp_rtcp/source/h264_sps_parser.cc
@@ -34,7 +34,7 @@
   // First, parse out rbsp, which is basically the source buffer minus emulation
   // bytes (the last byte of a 0x00 0x00 0x03 sequence). RBSP is defined in
   // section 7.3.1 of the H.264 standard.
-  rtc::ByteBuffer rbsp_buffer;
+  rtc::ByteBufferWriter rbsp_buffer;
   for (size_t i = 0; i < byte_length_;) {
     // Be careful about over/underflow here. byte_length_ - 3 can underflow, and
     // i + 3 can overflow, but byte_length_ - i can't, because i < byte_length_
diff --git a/webrtc/p2p/base/port.cc b/webrtc/p2p/base/port.cc
index 74b9edd..d26a930 100644
--- a/webrtc/p2p/base/port.cc
+++ b/webrtc/p2p/base/port.cc
@@ -343,7 +343,7 @@
   // Parse the request message.  If the packet is not a complete and correct
   // STUN message, then ignore it.
   rtc::scoped_ptr<IceMessage> stun_msg(new IceMessage());
-  rtc::ByteBuffer buf(data, size);
+  rtc::ByteBufferReader buf(data, size);
   if (!stun_msg->Read(&buf) || (buf.Length() > 0)) {
     return false;
   }
@@ -565,7 +565,7 @@
   response.AddFingerprint();
 
   // Send the response message.
-  rtc::ByteBuffer buf;
+  rtc::ByteBufferWriter buf;
   response.Write(&buf);
   rtc::PacketOptions options(DefaultDscpValue());
   auto err = SendTo(buf.Data(), buf.Length(), addr, options, false);
@@ -613,7 +613,7 @@
   response.AddFingerprint();
 
   // Send the response message.
-  rtc::ByteBuffer buf;
+  rtc::ByteBufferWriter buf;
   response.Write(&buf);
   rtc::PacketOptions options(DefaultDscpValue());
   SendTo(buf.Data(), buf.Length(), addr, options, false);
diff --git a/webrtc/p2p/base/port_unittest.cc b/webrtc/p2p/base/port_unittest.cc
index d27be29..fc49f20 100644
--- a/webrtc/p2p/base/port_unittest.cc
+++ b/webrtc/p2p/base/port_unittest.cc
@@ -18,6 +18,7 @@
 #include "webrtc/p2p/base/transport.h"
 #include "webrtc/p2p/base/turnport.h"
 #include "webrtc/base/arraysize.h"
+#include "webrtc/base/buffer.h"
 #include "webrtc/base/crc32.h"
 #include "webrtc/base/gunit.h"
 #include "webrtc/base/helpers.h"
@@ -33,7 +34,9 @@
 #include "webrtc/base/virtualsocketserver.h"
 
 using rtc::AsyncPacketSocket;
-using rtc::ByteBuffer;
+using rtc::Buffer;
+using rtc::ByteBufferReader;
+using rtc::ByteBufferWriter;
 using rtc::NATType;
 using rtc::NAT_OPEN_CONE;
 using rtc::NAT_ADDR_RESTRICTED;
@@ -84,13 +87,14 @@
 
 static IceMessage* CopyStunMessage(const IceMessage* src) {
   IceMessage* dst = new IceMessage();
-  ByteBuffer buf;
+  ByteBufferWriter buf;
   src->Write(&buf);
-  dst->Read(&buf);
+  ByteBufferReader read_buf(buf);
+  dst->Read(&read_buf);
   return dst;
 }
 
-static bool WriteStunMessage(const StunMessage* msg, ByteBuffer* buf) {
+static bool WriteStunMessage(const StunMessage* msg, ByteBufferWriter* buf) {
   buf->Resize(0);  // clear out any existing buffer contents
   return msg->Write(buf);
 }
@@ -123,7 +127,7 @@
 
   // The last StunMessage that was sent on this Port.
   // TODO: Make these const; requires changes to SendXXXXResponse.
-  ByteBuffer* last_stun_buf() { return last_stun_buf_.get(); }
+  Buffer* last_stun_buf() { return last_stun_buf_.get(); }
   IceMessage* last_stun_msg() { return last_stun_msg_.get(); }
   int last_stun_error_code() {
     int code = 0;
@@ -174,14 +178,13 @@
       const rtc::PacketOptions& options, bool payload) {
     if (!payload) {
       IceMessage* msg = new IceMessage;
-      ByteBuffer* buf = new ByteBuffer(static_cast<const char*>(data), size);
-      ByteBuffer::ReadPosition pos(buf->GetReadPosition());
-      if (!msg->Read(buf)) {
+      Buffer* buf = new Buffer(static_cast<const char*>(data), size);
+      ByteBufferReader read_buf(*buf);
+      if (!msg->Read(&read_buf)) {
         delete msg;
         delete buf;
         return -1;
       }
-      buf->SetReadPosition(pos);
       last_stun_buf_.reset(buf);
       last_stun_msg_.reset(msg);
     }
@@ -209,7 +212,7 @@
                     const rtc::SentPacket& sent_packet) {
     PortInterface::SignalSentPacket(sent_packet);
   }
-  rtc::scoped_ptr<ByteBuffer> last_stun_buf_;
+  rtc::scoped_ptr<Buffer> last_stun_buf_;
   rtc::scoped_ptr<IceMessage> last_stun_msg_;
   int type_preference_ = 0;
 };
@@ -1332,8 +1335,8 @@
   ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, 1000);
   IceMessage* msg = lport->last_stun_msg();
   EXPECT_EQ(STUN_BINDING_REQUEST, msg->type());
-  conn->OnReadPacket(lport->last_stun_buf()->Data(),
-                     lport->last_stun_buf()->Length(),
+  conn->OnReadPacket(lport->last_stun_buf()->data<char>(),
+                     lport->last_stun_buf()->size(),
                      rtc::PacketTime());
   ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, 1000);
   msg = lport->last_stun_msg();
@@ -1365,7 +1368,7 @@
   modified_req->AddFingerprint();
 
   lport->Reset();
-  rtc::scoped_ptr<ByteBuffer> buf(new ByteBuffer());
+  rtc::scoped_ptr<ByteBufferWriter> buf(new ByteBufferWriter());
   WriteStunMessage(modified_req.get(), buf.get());
   conn1->OnReadPacket(buf->Data(), buf->Length(), rtc::PacketTime());
   ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, 1000);
@@ -1402,8 +1405,8 @@
   IceMessage* msg = rport->last_stun_msg();
   EXPECT_EQ(STUN_BINDING_REQUEST, msg->type());
   // Send rport binding request to lport.
-  lconn->OnReadPacket(rport->last_stun_buf()->Data(),
-                      rport->last_stun_buf()->Length(),
+  lconn->OnReadPacket(rport->last_stun_buf()->data<char>(),
+                      rport->last_stun_buf()->size(),
                       rtc::PacketTime());
 
   ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, 1000);
@@ -1628,7 +1631,7 @@
   EXPECT_EQ("rfrag:lfrag", username_attr->GetString());
   EXPECT_TRUE(msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
   EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
-      lport->last_stun_buf()->Data(), lport->last_stun_buf()->Length(),
+      lport->last_stun_buf()->data<char>(), lport->last_stun_buf()->size(),
       "rpass"));
   const StunUInt64Attribute* ice_controlling_attr =
       msg->GetUInt64(STUN_ATTR_ICE_CONTROLLING);
@@ -1638,7 +1641,7 @@
   EXPECT_TRUE(msg->GetByteString(STUN_ATTR_USE_CANDIDATE) != NULL);
   EXPECT_TRUE(msg->GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
   EXPECT_TRUE(StunMessage::ValidateFingerprint(
-      lport->last_stun_buf()->Data(), lport->last_stun_buf()->Length()));
+      lport->last_stun_buf()->data<char>(), lport->last_stun_buf()->size()));
 
   // Request should not include ping count.
   ASSERT_TRUE(msg->GetUInt32(STUN_ATTR_RETRANSMIT_COUNT) == NULL);
@@ -1660,11 +1663,11 @@
   EXPECT_EQ(lport->Candidates()[0].address(), addr_attr->GetAddress());
   EXPECT_TRUE(msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
   EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
-      rport->last_stun_buf()->Data(), rport->last_stun_buf()->Length(),
+      rport->last_stun_buf()->data<char>(), rport->last_stun_buf()->size(),
       "rpass"));
   EXPECT_TRUE(msg->GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
   EXPECT_TRUE(StunMessage::ValidateFingerprint(
-      lport->last_stun_buf()->Data(), lport->last_stun_buf()->Length()));
+      lport->last_stun_buf()->data<char>(), lport->last_stun_buf()->size()));
   // No USERNAME or PRIORITY in ICE responses.
   EXPECT_TRUE(msg->GetByteString(STUN_ATTR_USERNAME) == NULL);
   EXPECT_TRUE(msg->GetByteString(STUN_ATTR_PRIORITY) == NULL);
@@ -1692,11 +1695,11 @@
   EXPECT_EQ(std::string(STUN_ERROR_REASON_SERVER_ERROR), error_attr->reason());
   EXPECT_TRUE(msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
   EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
-      rport->last_stun_buf()->Data(), rport->last_stun_buf()->Length(),
+      rport->last_stun_buf()->data<char>(), rport->last_stun_buf()->size(),
       "rpass"));
   EXPECT_TRUE(msg->GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
   EXPECT_TRUE(StunMessage::ValidateFingerprint(
-      lport->last_stun_buf()->Data(), lport->last_stun_buf()->Length()));
+      lport->last_stun_buf()->data<char>(), lport->last_stun_buf()->size()));
   // No USERNAME with ICE.
   EXPECT_TRUE(msg->GetByteString(STUN_ATTR_USERNAME) == NULL);
   EXPECT_TRUE(msg->GetByteString(STUN_ATTR_PRIORITY) == NULL);
@@ -1813,7 +1816,7 @@
       CreateTestPort(kLocalAddr2, "rfrag", "rpass"));
 
   rtc::scoped_ptr<IceMessage> in_msg, out_msg;
-  rtc::scoped_ptr<ByteBuffer> buf(new ByteBuffer());
+  rtc::scoped_ptr<ByteBufferWriter> buf(new ByteBufferWriter());
   rtc::SocketAddress addr(kLocalAddr1);
   std::string username;
 
@@ -1863,7 +1866,7 @@
       CreateTestPort(kLocalAddr2, "rfrag", "rpass"));
 
   rtc::scoped_ptr<IceMessage> in_msg, out_msg;
-  rtc::scoped_ptr<ByteBuffer> buf(new ByteBuffer());
+  rtc::scoped_ptr<ByteBufferWriter> buf(new ByteBufferWriter());
   rtc::SocketAddress addr(kLocalAddr1);
   std::string username;
 
@@ -1932,7 +1935,7 @@
       CreateTestPort(kLocalAddr2, "rfrag", "rpass"));
 
   rtc::scoped_ptr<IceMessage> in_msg, out_msg;
-  rtc::scoped_ptr<ByteBuffer> buf(new ByteBuffer());
+  rtc::scoped_ptr<ByteBufferWriter> buf(new ByteBufferWriter());
   rtc::SocketAddress addr(kLocalAddr1);
   std::string username;
 
@@ -1973,7 +1976,7 @@
       CreateTestPort(kLocalAddr2, "rfrag", "rpass"));
 
   rtc::scoped_ptr<IceMessage> in_msg, out_msg;
-  rtc::scoped_ptr<ByteBuffer> buf(new ByteBuffer());
+  rtc::scoped_ptr<ByteBufferWriter> buf(new ByteBufferWriter());
   rtc::SocketAddress addr(kLocalAddr1);
   std::string username;
 
@@ -2042,7 +2045,7 @@
 
   // Verifying encoding and decoding STUN indication message.
   rtc::scoped_ptr<IceMessage> in_msg, out_msg;
-  rtc::scoped_ptr<ByteBuffer> buf(new ByteBuffer());
+  rtc::scoped_ptr<ByteBufferWriter> buf(new ByteBufferWriter());
   rtc::SocketAddress addr(kLocalAddr1);
   std::string username;
 
@@ -2077,8 +2080,8 @@
   IceMessage* msg = rport->last_stun_msg();
   EXPECT_EQ(STUN_BINDING_REQUEST, msg->type());
   // Send rport binding request to lport.
-  lconn->OnReadPacket(rport->last_stun_buf()->Data(),
-                      rport->last_stun_buf()->Length(),
+  lconn->OnReadPacket(rport->last_stun_buf()->data<char>(),
+                      rport->last_stun_buf()->size(),
                       rtc::PacketTime());
   ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, 1000);
   EXPECT_EQ(STUN_BINDING_RESPONSE, lport->last_stun_msg()->type());
@@ -2464,8 +2467,8 @@
       request.get(), ice_full_port->Candidates()[0].address());
 
   // Feeding the respone message from litemode to the full mode connection.
-  ch1.conn()->OnReadPacket(ice_lite_port->last_stun_buf()->Data(),
-                           ice_lite_port->last_stun_buf()->Length(),
+  ch1.conn()->OnReadPacket(ice_lite_port->last_stun_buf()->data<char>(),
+                           ice_lite_port->last_stun_buf()->size(),
                            rtc::PacketTime());
   // Verifying full mode connection becomes writable from the response.
   EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, ch1.conn()->write_state(),
diff --git a/webrtc/p2p/base/pseudotcp.cc b/webrtc/p2p/base/pseudotcp.cc
index 6281315..1dfdcbb 100644
--- a/webrtc/p2p/base/pseudotcp.cc
+++ b/webrtc/p2p/base/pseudotcp.cc
@@ -1168,7 +1168,7 @@
 
 void
 PseudoTcp::queueConnectMessage() {
-  rtc::ByteBuffer buf(rtc::ByteBuffer::ORDER_NETWORK);
+  rtc::ByteBufferWriter buf(rtc::ByteBuffer::ORDER_NETWORK);
 
   buf.WriteUInt8(CTL_CONNECT);
   if (m_support_wnd_scale) {
@@ -1185,7 +1185,7 @@
 
   // See http://www.freesoft.org/CIE/Course/Section4/8.htm for
   // parsing the options list.
-  rtc::ByteBuffer buf(data, len);
+  rtc::ByteBufferReader buf(data, len);
   while (buf.Length()) {
     uint8_t kind = TCP_OPT_EOL;
     buf.ReadUInt8(&kind);
diff --git a/webrtc/p2p/base/relayport.cc b/webrtc/p2p/base/relayport.cc
index f5ad911..7196043 100644
--- a/webrtc/p2p/base/relayport.cc
+++ b/webrtc/p2p/base/relayport.cc
@@ -607,7 +607,7 @@
 
   // TODO: compute the HMAC.
 
-  rtc::ByteBuffer buf;
+  rtc::ByteBufferWriter buf;
   request.Write(&buf);
 
   return SendPacket(buf.Data(), buf.Length(), options);
@@ -703,7 +703,7 @@
     return;
   }
 
-  rtc::ByteBuffer buf(data, size);
+  rtc::ByteBufferReader buf(data, size);
   RelayMessage msg;
   if (!msg.Read(&buf)) {
     LOG(INFO) << "Incoming packet was not STUN";
diff --git a/webrtc/p2p/base/relayserver.cc b/webrtc/p2p/base/relayserver.cc
index aad0070..e098cbc 100644
--- a/webrtc/p2p/base/relayserver.cc
+++ b/webrtc/p2p/base/relayserver.cc
@@ -46,7 +46,7 @@
 void SendStun(const StunMessage& msg,
               rtc::AsyncPacketSocket* socket,
               const rtc::SocketAddress& addr) {
-  rtc::ByteBuffer buf;
+  rtc::ByteBufferWriter buf;
   msg.Write(&buf);
   Send(socket, buf.Data(), buf.Length(), addr);
 }
@@ -249,7 +249,7 @@
   // The first packet should always be a STUN / TURN packet.  If it isn't, then
   // we should just ignore this packet.
   RelayMessage msg;
-  rtc::ByteBuffer buf(bytes, size);
+  rtc::ByteBufferReader buf(bytes, size);
   if (!msg.Read(&buf)) {
     LOG(LS_WARNING) << "Dropping packet: first packet not STUN";
     return;
@@ -298,7 +298,7 @@
     StunMessage* msg) {
 
   // Parse this into a stun message. Eat the message if this fails.
-  rtc::ByteBuffer buf(bytes, size);
+  rtc::ByteBufferReader buf(bytes, size);
   if (!msg->Read(&buf)) {
     return false;
   }
diff --git a/webrtc/p2p/base/relayserver_unittest.cc b/webrtc/p2p/base/relayserver_unittest.cc
index 83e5353..3581f71 100644
--- a/webrtc/p2p/base/relayserver_unittest.cc
+++ b/webrtc/p2p/base/relayserver_unittest.cc
@@ -76,12 +76,12 @@
   }
 
   void Send1(const StunMessage* msg) {
-    rtc::ByteBuffer buf;
+    rtc::ByteBufferWriter buf;
     msg->Write(&buf);
     SendRaw1(buf.Data(), static_cast<int>(buf.Length()));
   }
   void Send2(const StunMessage* msg) {
-    rtc::ByteBuffer buf;
+    rtc::ByteBufferWriter buf;
     msg->Write(&buf);
     SendRaw2(buf.Data(), static_cast<int>(buf.Length()));
   }
@@ -120,9 +120,10 @@
     rtc::TestClient::Packet* packet =
         client->NextPacket(rtc::TestClient::kTimeoutMs);
     if (packet) {
-      rtc::ByteBuffer buf(packet->buf, packet->size);
+      rtc::ByteBufferWriter buf(packet->buf, packet->size);
+      rtc::ByteBufferReader read_buf(buf);
       msg = new RelayMessage();
-      msg->Read(&buf);
+      msg->Read(&read_buf);
       delete packet;
     }
     return msg;
@@ -302,7 +303,7 @@
       res->GetByteString(STUN_ATTR_DATA);
   ASSERT_TRUE(recv_data != NULL);
 
-  rtc::ByteBuffer buf(recv_data->bytes(), recv_data->length());
+  rtc::ByteBufferReader buf(recv_data->bytes(), recv_data->length());
   rtc::scoped_ptr<StunMessage> res2(new StunMessage());
   EXPECT_TRUE(res2->Read(&buf));
   EXPECT_EQ(STUN_BINDING_REQUEST, res2->type());
diff --git a/webrtc/p2p/base/stun.cc b/webrtc/p2p/base/stun.cc
index 9c22995..d0f0014 100644
--- a/webrtc/p2p/base/stun.cc
+++ b/webrtc/p2p/base/stun.cc
@@ -20,7 +20,8 @@
 #include "webrtc/base/scoped_ptr.h"
 #include "webrtc/base/stringencode.h"
 
-using rtc::ByteBuffer;
+using rtc::ByteBufferReader;
+using rtc::ByteBufferWriter;
 
 namespace cricket {
 
@@ -219,7 +220,7 @@
   VERIFY(AddAttribute(msg_integrity_attr));
 
   // Calculate the HMAC for the message.
-  rtc::ByteBuffer buf;
+  ByteBufferWriter buf;
   if (!Write(&buf))
     return false;
 
@@ -280,7 +281,7 @@
   VERIFY(AddAttribute(fingerprint_attr));
 
   // Calculate the CRC-32 for the message and insert it.
-  rtc::ByteBuffer buf;
+  ByteBufferWriter buf;
   if (!Write(&buf))
     return false;
 
@@ -293,7 +294,7 @@
   return true;
 }
 
-bool StunMessage::Read(ByteBuffer* buf) {
+bool StunMessage::Read(ByteBufferReader* buf) {
   if (!buf->ReadUInt16(&type_))
     return false;
 
@@ -356,7 +357,7 @@
   return true;
 }
 
-bool StunMessage::Write(ByteBuffer* buf) const {
+bool StunMessage::Write(ByteBufferWriter* buf) const {
   buf->WriteUInt16(type_);
   buf->WriteUInt16(length_);
   if (!IsLegacy())
@@ -417,14 +418,14 @@
     : type_(type), length_(length) {
 }
 
-void StunAttribute::ConsumePadding(rtc::ByteBuffer* buf) const {
+void StunAttribute::ConsumePadding(ByteBufferReader* buf) const {
   int remainder = length_ % 4;
   if (remainder > 0) {
     buf->Consume(4 - remainder);
   }
 }
 
-void StunAttribute::WritePadding(rtc::ByteBuffer* buf) const {
+void StunAttribute::WritePadding(ByteBufferWriter* buf) const {
   int remainder = length_ % 4;
   if (remainder > 0) {
     char zeroes[4] = {0};
@@ -495,7 +496,7 @@
     : StunAttribute(type, length) {
 }
 
-bool StunAddressAttribute::Read(ByteBuffer* buf) {
+bool StunAddressAttribute::Read(ByteBufferReader* buf) {
   uint8_t dummy;
   if (!buf->ReadUInt8(&dummy))
     return false;
@@ -533,7 +534,7 @@
   return true;
 }
 
-bool StunAddressAttribute::Write(ByteBuffer* buf) const {
+bool StunAddressAttribute::Write(ByteBufferWriter* buf) const {
   StunAddressFamily address_family = family();
   if (address_family == STUN_ADDRESS_UNDEF) {
     LOG(LS_ERROR) << "Error writing address attribute: unknown family.";
@@ -604,7 +605,7 @@
   return rtc::IPAddress();
 }
 
-bool StunXorAddressAttribute::Read(ByteBuffer* buf) {
+bool StunXorAddressAttribute::Read(ByteBufferReader* buf) {
   if (!StunAddressAttribute::Read(buf))
     return false;
   uint16_t xoredport = port() ^ (kStunMagicCookie >> 16);
@@ -613,7 +614,7 @@
   return true;
 }
 
-bool StunXorAddressAttribute::Write(ByteBuffer* buf) const {
+bool StunXorAddressAttribute::Write(ByteBufferWriter* buf) const {
   StunAddressFamily address_family = family();
   if (address_family == STUN_ADDRESS_UNDEF) {
     LOG(LS_ERROR) << "Error writing xor-address attribute: unknown family.";
@@ -660,13 +661,13 @@
   bits_ |= value ? (1 << index) : 0;
 }
 
-bool StunUInt32Attribute::Read(ByteBuffer* buf) {
+bool StunUInt32Attribute::Read(ByteBufferReader* buf) {
   if (length() != SIZE || !buf->ReadUInt32(&bits_))
     return false;
   return true;
 }
 
-bool StunUInt32Attribute::Write(ByteBuffer* buf) const {
+bool StunUInt32Attribute::Write(ByteBufferWriter* buf) const {
   buf->WriteUInt32(bits_);
   return true;
 }
@@ -679,13 +680,13 @@
     : StunAttribute(type, SIZE), bits_(0) {
 }
 
-bool StunUInt64Attribute::Read(ByteBuffer* buf) {
+bool StunUInt64Attribute::Read(ByteBufferReader* buf) {
   if (length() != SIZE || !buf->ReadUInt64(&bits_))
     return false;
   return true;
 }
 
-bool StunUInt64Attribute::Write(ByteBuffer* buf) const {
+bool StunUInt64Attribute::Write(ByteBufferWriter* buf) const {
   buf->WriteUInt64(bits_);
   return true;
 }
@@ -737,7 +738,7 @@
   bytes_[index] = value;
 }
 
-bool StunByteStringAttribute::Read(ByteBuffer* buf) {
+bool StunByteStringAttribute::Read(ByteBufferReader* buf) {
   bytes_ = new char[length()];
   if (!buf->ReadBytes(bytes_, length())) {
     return false;
@@ -747,7 +748,7 @@
   return true;
 }
 
-bool StunByteStringAttribute::Write(ByteBuffer* buf) const {
+bool StunByteStringAttribute::Write(ByteBufferWriter* buf) const {
   buf->WriteBytes(bytes_, length());
   WritePadding(buf);
   return true;
@@ -788,7 +789,7 @@
   reason_ = reason;
 }
 
-bool StunErrorCodeAttribute::Read(ByteBuffer* buf) {
+bool StunErrorCodeAttribute::Read(ByteBufferReader* buf) {
   uint32_t val;
   if (length() < MIN_SIZE || !buf->ReadUInt32(&val))
     return false;
@@ -806,7 +807,7 @@
   return true;
 }
 
-bool StunErrorCodeAttribute::Write(ByteBuffer* buf) const {
+bool StunErrorCodeAttribute::Write(ByteBufferWriter* buf) const {
   buf->WriteUInt32(class_ << 8 | number_);
   buf->WriteString(reason_);
   WritePadding(buf);
@@ -839,7 +840,7 @@
   SetLength(static_cast<uint16_t>(attr_types_->size() * 2));
 }
 
-bool StunUInt16ListAttribute::Read(ByteBuffer* buf) {
+bool StunUInt16ListAttribute::Read(ByteBufferReader* buf) {
   if (length() % 2)
     return false;
 
@@ -858,7 +859,7 @@
   return true;
 }
 
-bool StunUInt16ListAttribute::Write(ByteBuffer* buf) const {
+bool StunUInt16ListAttribute::Write(ByteBufferWriter* buf) const {
   for (size_t i = 0; i < attr_types_->size(); ++i) {
     buf->WriteUInt16((*attr_types_)[i]);
   }
diff --git a/webrtc/p2p/base/stun.h b/webrtc/p2p/base/stun.h
index aada43c..c0f5cfd 100644
--- a/webrtc/p2p/base/stun.h
+++ b/webrtc/p2p/base/stun.h
@@ -180,11 +180,11 @@
 
   // Parses the STUN packet in the given buffer and records it here. The
   // return value indicates whether this was successful.
-  bool Read(rtc::ByteBuffer* buf);
+  bool Read(rtc::ByteBufferReader* buf);
 
   // Writes this object into a STUN packet. The return value indicates whether
   // this was successful.
-  bool Write(rtc::ByteBuffer* buf) const;
+  bool Write(rtc::ByteBufferWriter* buf) const;
 
   // Creates an empty message. Overridable by derived classes.
   virtual StunMessage* CreateNew() const { return new StunMessage(); }
@@ -221,11 +221,11 @@
 
   // Reads the body (not the type or length) for this type of attribute from
   // the given buffer.  Return value is true if successful.
-  virtual bool Read(rtc::ByteBuffer* buf) = 0;
+  virtual bool Read(rtc::ByteBufferReader* buf) = 0;
 
   // Writes the body (not the type or length) to the given buffer.  Return
   // value is true if successful.
-  virtual bool Write(rtc::ByteBuffer* buf) const = 0;
+  virtual bool Write(rtc::ByteBufferWriter* buf) const = 0;
 
   // Creates an attribute object with the given type and smallest length.
   static StunAttribute* Create(StunAttributeValueType value_type,
@@ -245,8 +245,8 @@
  protected:
   StunAttribute(uint16_t type, uint16_t length);
   void SetLength(uint16_t length) { length_ = length; }
-  void WritePadding(rtc::ByteBuffer* buf) const;
-  void ConsumePadding(rtc::ByteBuffer* buf) const;
+  void WritePadding(rtc::ByteBufferWriter* buf) const;
+  void ConsumePadding(rtc::ByteBufferReader* buf) const;
 
  private:
   uint16_t type_;
@@ -290,8 +290,8 @@
   }
   void SetPort(uint16_t port) { address_.SetPort(port); }
 
-  virtual bool Read(rtc::ByteBuffer* buf);
-  virtual bool Write(rtc::ByteBuffer* buf) const;
+  virtual bool Read(rtc::ByteBufferReader* buf);
+  virtual bool Write(rtc::ByteBufferWriter* buf) const;
 
  private:
   void EnsureAddressLength() {
@@ -327,8 +327,8 @@
   virtual void SetOwner(StunMessage* owner) {
     owner_ = owner;
   }
-  virtual bool Read(rtc::ByteBuffer* buf);
-  virtual bool Write(rtc::ByteBuffer* buf) const;
+  virtual bool Read(rtc::ByteBufferReader* buf);
+  virtual bool Write(rtc::ByteBufferWriter* buf) const;
 
  private:
   rtc::IPAddress GetXoredIP() const;
@@ -352,8 +352,8 @@
   bool GetBit(size_t index) const;
   void SetBit(size_t index, bool value);
 
-  virtual bool Read(rtc::ByteBuffer* buf);
-  virtual bool Write(rtc::ByteBuffer* buf) const;
+  virtual bool Read(rtc::ByteBufferReader* buf);
+  virtual bool Write(rtc::ByteBufferWriter* buf) const;
 
  private:
   uint32_t bits_;
@@ -372,8 +372,8 @@
   uint64_t value() const { return bits_; }
   void SetValue(uint64_t bits) { bits_ = bits; }
 
-  virtual bool Read(rtc::ByteBuffer* buf);
-  virtual bool Write(rtc::ByteBuffer* buf) const;
+  virtual bool Read(rtc::ByteBufferReader* buf);
+  virtual bool Write(rtc::ByteBufferWriter* buf) const;
 
  private:
   uint64_t bits_;
@@ -401,8 +401,8 @@
   uint8_t GetByte(size_t index) const;
   void SetByte(size_t index, uint8_t value);
 
-  virtual bool Read(rtc::ByteBuffer* buf);
-  virtual bool Write(rtc::ByteBuffer* buf) const;
+  virtual bool Read(rtc::ByteBufferReader* buf);
+  virtual bool Write(rtc::ByteBufferWriter* buf) const;
 
  private:
   void SetBytes(char* bytes, size_t length);
@@ -434,8 +434,8 @@
   void SetNumber(uint8_t number) { number_ = number; }
   void SetReason(const std::string& reason);
 
-  bool Read(rtc::ByteBuffer* buf);
-  bool Write(rtc::ByteBuffer* buf) const;
+  bool Read(rtc::ByteBufferReader* buf);
+  bool Write(rtc::ByteBufferWriter* buf) const;
 
  private:
   uint8_t class_;
@@ -458,8 +458,8 @@
   void SetType(int index, uint16_t value);
   void AddType(uint16_t value);
 
-  bool Read(rtc::ByteBuffer* buf);
-  bool Write(rtc::ByteBuffer* buf) const;
+  bool Read(rtc::ByteBufferReader* buf);
+  bool Write(rtc::ByteBufferWriter* buf) const;
 
  private:
   std::vector<uint16_t>* attr_types_;
diff --git a/webrtc/p2p/base/stun_unittest.cc b/webrtc/p2p/base/stun_unittest.cc
index 1249257..2213397 100644
--- a/webrtc/p2p/base/stun_unittest.cc
+++ b/webrtc/p2p/base/stun_unittest.cc
@@ -62,7 +62,7 @@
                                  const unsigned char* testcase,
                                  size_t size) {
     const char* input = reinterpret_cast<const char*>(testcase);
-    rtc::ByteBuffer buf(input, size);
+    rtc::ByteBufferReader buf(input, size);
     if (msg->Read(&buf)) {
       // Returns the size the stun message should report itself as being
       return (size - 20);
@@ -739,22 +739,23 @@
   // The internal IP address shouldn't change.
   ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
 
-  rtc::ByteBuffer correct_buf;
-  rtc::ByteBuffer wrong_buf;
+  rtc::ByteBufferWriter correct_buf;
+  rtc::ByteBufferWriter wrong_buf;
   EXPECT_TRUE(addr->Write(&correct_buf));
   EXPECT_TRUE(addr2.Write(&wrong_buf));
   // But when written out, the buffers should look different.
   ASSERT_NE(0,
             memcmp(correct_buf.Data(), wrong_buf.Data(), wrong_buf.Length()));
   // And when reading a known good value, the address should be wrong.
-  addr2.Read(&correct_buf);
+  rtc::ByteBufferReader read_buf(correct_buf);
+  addr2.Read(&read_buf);
   ASSERT_NE(addr->ipaddr(), addr2.ipaddr());
   addr2.SetIP(addr->ipaddr());
   addr2.SetPort(addr->port());
   // Try writing with no owner at all, should fail and write nothing.
   addr2.SetOwner(NULL);
   ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
-  wrong_buf.Consume(wrong_buf.Length());
+  wrong_buf.Clear();
   EXPECT_FALSE(addr2.Write(&wrong_buf));
   ASSERT_EQ(0U, wrong_buf.Length());
 }
@@ -786,8 +787,8 @@
   // The internal IP address shouldn't change.
   ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
 
-  rtc::ByteBuffer correct_buf;
-  rtc::ByteBuffer wrong_buf;
+  rtc::ByteBufferWriter correct_buf;
+  rtc::ByteBufferWriter wrong_buf;
   EXPECT_TRUE(addr->Write(&correct_buf));
   EXPECT_TRUE(addr2.Write(&wrong_buf));
   // The same address data should be written.
@@ -795,13 +796,14 @@
             memcmp(correct_buf.Data(), wrong_buf.Data(), wrong_buf.Length()));
   // And an attribute should be able to un-XOR an address belonging to a message
   // with a different transaction ID.
-  EXPECT_TRUE(addr2.Read(&correct_buf));
+  rtc::ByteBufferReader read_buf(correct_buf);
+  EXPECT_TRUE(addr2.Read(&read_buf));
   ASSERT_EQ(addr->ipaddr(), addr2.ipaddr());
 
   // However, no owner is still an error, should fail and write nothing.
   addr2.SetOwner(NULL);
   ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
-  wrong_buf.Consume(wrong_buf.Length());
+  wrong_buf.Clear();
   EXPECT_FALSE(addr2.Write(&wrong_buf));
 }
 
@@ -875,12 +877,13 @@
 
   CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
 
-  rtc::ByteBuffer out;
+  rtc::ByteBufferWriter out;
   EXPECT_TRUE(msg.Write(&out));
   ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv6MappedAddress));
   int len1 = static_cast<int>(out.Length());
+  rtc::ByteBufferReader read_buf(out);
   std::string bytes;
-  out.ReadString(&bytes, len1);
+  read_buf.ReadString(&bytes, len1);
   ASSERT_EQ(0, memcmp(bytes.c_str(), kStunMessageWithIPv6MappedAddress, len1));
 }
 
@@ -904,12 +907,13 @@
 
   CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
 
-  rtc::ByteBuffer out;
+  rtc::ByteBufferWriter out;
   EXPECT_TRUE(msg.Write(&out));
   ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv4MappedAddress));
   int len1 = static_cast<int>(out.Length());
+  rtc::ByteBufferReader read_buf(out);
   std::string bytes;
-  out.ReadString(&bytes, len1);
+  read_buf.ReadString(&bytes, len1);
   ASSERT_EQ(0, memcmp(bytes.c_str(), kStunMessageWithIPv4MappedAddress, len1));
 }
 
@@ -933,12 +937,13 @@
 
   CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
 
-  rtc::ByteBuffer out;
+  rtc::ByteBufferWriter out;
   EXPECT_TRUE(msg.Write(&out));
   ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv6XorMappedAddress));
   int len1 = static_cast<int>(out.Length());
+  rtc::ByteBufferReader read_buf(out);
   std::string bytes;
-  out.ReadString(&bytes, len1);
+  read_buf.ReadString(&bytes, len1);
   ASSERT_EQ(0,
             memcmp(bytes.c_str(), kStunMessageWithIPv6XorMappedAddress, len1));
 }
@@ -963,12 +968,13 @@
 
   CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
 
-  rtc::ByteBuffer out;
+  rtc::ByteBufferWriter out;
   EXPECT_TRUE(msg.Write(&out));
   ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv4XorMappedAddress));
   int len1 = static_cast<int>(out.Length());
+  rtc::ByteBufferReader read_buf(out);
   std::string bytes;
-  out.ReadString(&bytes, len1);
+  read_buf.ReadString(&bytes, len1);
   ASSERT_EQ(0,
             memcmp(bytes.c_str(), kStunMessageWithIPv4XorMappedAddress, len1));
 }
@@ -1061,7 +1067,7 @@
   EXPECT_TRUE(msg.AddAttribute(errorcode));
   CheckStunHeader(msg, STUN_BINDING_ERROR_RESPONSE, (size - 20));
 
-  rtc::ByteBuffer out;
+  rtc::ByteBufferWriter out;
   EXPECT_TRUE(msg.Write(&out));
   ASSERT_EQ(size, out.Length());
   // No padding.
@@ -1084,7 +1090,7 @@
   EXPECT_TRUE(msg.AddAttribute(list));
   CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
 
-  rtc::ByteBuffer out;
+  rtc::ByteBufferWriter out;
   EXPECT_TRUE(msg.Write(&out));
   ASSERT_EQ(size, out.Length());
   // Check everything up to the padding.
@@ -1104,7 +1110,7 @@
       new StunByteStringAttribute(STUN_ATTR_ORIGIN, kTestOrigin);
   EXPECT_TRUE(msg.AddAttribute(origin));
 
-  rtc::ByteBuffer out;
+  rtc::ByteBufferWriter out;
   EXPECT_TRUE(msg.Write(&out));
   ASSERT_EQ(size, out.Length());
   // Check everything up to the padding
@@ -1115,7 +1121,7 @@
 void CheckFailureToRead(const unsigned char* testcase, size_t length) {
   StunMessage msg;
   const char* input = reinterpret_cast<const char*>(testcase);
-  rtc::ByteBuffer buf(input, length);
+  rtc::ByteBufferReader buf(input, length);
   ASSERT_FALSE(msg.Read(&buf));
 }
 
@@ -1207,7 +1213,7 @@
 // the RFC5769 test messages used include attributes not found in basic STUN.
 TEST_F(StunTest, AddMessageIntegrity) {
   IceMessage msg;
-  rtc::ByteBuffer buf(
+  rtc::ByteBufferReader buf(
       reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
       sizeof(kRfc5769SampleRequestWithoutMI));
   EXPECT_TRUE(msg.Read(&buf));
@@ -1218,14 +1224,14 @@
   EXPECT_EQ(0, memcmp(
       mi_attr->bytes(), kCalculatedHmac1, sizeof(kCalculatedHmac1)));
 
-  rtc::ByteBuffer buf1;
+  rtc::ByteBufferWriter buf1;
   EXPECT_TRUE(msg.Write(&buf1));
   EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
         reinterpret_cast<const char*>(buf1.Data()), buf1.Length(),
         kRfc5769SampleMsgPassword));
 
   IceMessage msg2;
-  rtc::ByteBuffer buf2(
+  rtc::ByteBufferReader buf2(
       reinterpret_cast<const char*>(kRfc5769SampleResponseWithoutMI),
       sizeof(kRfc5769SampleResponseWithoutMI));
   EXPECT_TRUE(msg2.Read(&buf2));
@@ -1236,7 +1242,7 @@
   EXPECT_EQ(
       0, memcmp(mi_attr2->bytes(), kCalculatedHmac2, sizeof(kCalculatedHmac2)));
 
-  rtc::ByteBuffer buf3;
+  rtc::ByteBufferWriter buf3;
   EXPECT_TRUE(msg2.Write(&buf3));
   EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
         reinterpret_cast<const char*>(buf3.Data()), buf3.Length(),
@@ -1282,13 +1288,13 @@
 
 TEST_F(StunTest, AddFingerprint) {
   IceMessage msg;
-  rtc::ByteBuffer buf(
+  rtc::ByteBufferReader buf(
       reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
       sizeof(kRfc5769SampleRequestWithoutMI));
   EXPECT_TRUE(msg.Read(&buf));
   EXPECT_TRUE(msg.AddFingerprint());
 
-  rtc::ByteBuffer buf1;
+  rtc::ByteBufferWriter buf1;
   EXPECT_TRUE(msg.Write(&buf1));
   EXPECT_TRUE(StunMessage::ValidateFingerprint(
       reinterpret_cast<const char*>(buf1.Data()), buf1.Length()));
@@ -1331,7 +1337,7 @@
 
   const char* input = reinterpret_cast<const char*>(kRelayMessage);
   size_t size = sizeof(kRelayMessage);
-  rtc::ByteBuffer buf(input, size);
+  rtc::ByteBufferReader buf(input, size);
   EXPECT_TRUE(msg.Read(&buf));
 
   EXPECT_EQ(STUN_BINDING_REQUEST, msg.type());
@@ -1427,20 +1433,22 @@
   bytes2->CopyBytes("abcdefg");
   EXPECT_TRUE(msg2.AddAttribute(bytes2));
 
-  rtc::ByteBuffer out;
+  rtc::ByteBufferWriter out;
   EXPECT_TRUE(msg.Write(&out));
   EXPECT_EQ(size, out.Length());
   size_t len1 = out.Length();
+  rtc::ByteBufferReader read_buf(out);
   std::string outstring;
-  out.ReadString(&outstring, len1);
+  read_buf.ReadString(&outstring, len1);
   EXPECT_EQ(0, memcmp(outstring.c_str(), input, len1));
 
-  rtc::ByteBuffer out2;
+  rtc::ByteBufferWriter out2;
   EXPECT_TRUE(msg2.Write(&out2));
   EXPECT_EQ(size, out2.Length());
   size_t len2 = out2.Length();
+  rtc::ByteBufferReader read_buf2(out2);
   std::string outstring2;
-  out2.ReadString(&outstring2, len2);
+  read_buf2.ReadString(&outstring2, len2);
   EXPECT_EQ(0, memcmp(outstring2.c_str(), input, len2));
 }
 
diff --git a/webrtc/p2p/base/stunrequest.cc b/webrtc/p2p/base/stunrequest.cc
index 9ceb6da..546dd15 100644
--- a/webrtc/p2p/base/stunrequest.cc
+++ b/webrtc/p2p/base/stunrequest.cc
@@ -138,7 +138,7 @@
 
   // Parse the STUN message and continue processing as usual.
 
-  rtc::ByteBuffer buf(data, size);
+  rtc::ByteBufferReader buf(data, size);
   rtc::scoped_ptr<StunMessage> response(iter->second->msg_->CreateNew());
   if (!response->Read(&buf)) {
     LOG(LS_WARNING) << "Failed to read STUN response " << rtc::hex_encode(id);
@@ -213,7 +213,7 @@
 
   tstamp_ = rtc::Time64();
 
-  rtc::ByteBuffer buf;
+  rtc::ByteBufferWriter buf;
   msg_->Write(&buf);
   manager_->SignalSendPacket(buf.Data(), buf.Length(), this);
 
diff --git a/webrtc/p2p/base/stunserver.cc b/webrtc/p2p/base/stunserver.cc
index fbc316b..bac9fd5 100644
--- a/webrtc/p2p/base/stunserver.cc
+++ b/webrtc/p2p/base/stunserver.cc
@@ -28,7 +28,7 @@
     const rtc::SocketAddress& remote_addr,
     const rtc::PacketTime& packet_time) {
   // Parse the STUN message; eat any messages that fail to parse.
-  rtc::ByteBuffer bbuf(buf, size);
+  rtc::ByteBufferReader bbuf(buf, size);
   StunMessage msg;
   if (!msg.Read(&bbuf)) {
     return;
@@ -72,7 +72,7 @@
 
 void StunServer::SendResponse(
     const StunMessage& msg, const rtc::SocketAddress& addr) {
-  rtc::ByteBuffer buf;
+  rtc::ByteBufferWriter buf;
   msg.Write(&buf);
   rtc::PacketOptions options;
   if (socket_->SendTo(buf.Data(), buf.Length(), addr, options) < 0)
diff --git a/webrtc/p2p/base/stunserver_unittest.cc b/webrtc/p2p/base/stunserver_unittest.cc
index d405979..973ab2a 100644
--- a/webrtc/p2p/base/stunserver_unittest.cc
+++ b/webrtc/p2p/base/stunserver_unittest.cc
@@ -39,7 +39,7 @@
     worker_.Start();
   }
   void Send(const StunMessage& msg) {
-    rtc::ByteBuffer buf;
+    rtc::ByteBufferWriter buf;
     msg.Write(&buf);
     Send(buf.Data(), static_cast<int>(buf.Length()));
   }
@@ -54,7 +54,7 @@
     rtc::TestClient::Packet* packet =
         client_->NextPacket(rtc::TestClient::kTimeoutMs);
     if (packet) {
-      rtc::ByteBuffer buf(packet->buf, packet->size);
+      rtc::ByteBufferReader buf(packet->buf, packet->size);
       msg = new StunMessage();
       msg->Read(&buf);
       delete packet;
diff --git a/webrtc/p2p/base/turnport.cc b/webrtc/p2p/base/turnport.cc
index 5f719ce..9ea354c 100644
--- a/webrtc/p2p/base/turnport.cc
+++ b/webrtc/p2p/base/turnport.cc
@@ -786,7 +786,7 @@
 void TurnPort::HandleDataIndication(const char* data, size_t size,
                                     const rtc::PacketTime& packet_time) {
   // Read in the message, and process according to RFC5766, Section 10.4.
-  rtc::ByteBuffer buf(data, size);
+  rtc::ByteBufferReader buf(data, size);
   TurnMessage msg;
   if (!msg.Read(&buf)) {
     LOG_J(LS_WARNING, this) << "Received invalid TURN data indication";
@@ -1425,7 +1425,7 @@
 
 int TurnEntry::Send(const void* data, size_t size, bool payload,
                     const rtc::PacketOptions& options) {
-  rtc::ByteBuffer buf;
+  rtc::ByteBufferWriter buf;
   if (state_ != STATE_BOUND) {
     // If we haven't bound the channel yet, we have to use a Send Indication.
     TurnMessage msg;
diff --git a/webrtc/p2p/base/turnserver.cc b/webrtc/p2p/base/turnserver.cc
index 14dcf05..13974a0 100644
--- a/webrtc/p2p/base/turnserver.cc
+++ b/webrtc/p2p/base/turnserver.cc
@@ -216,7 +216,7 @@
 void TurnServer::HandleStunMessage(TurnServerConnection* conn, const char* data,
                                    size_t size) {
   TurnMessage msg;
-  rtc::ByteBuffer buf(data, size);
+  rtc::ByteBufferReader buf(data, size);
   if (!msg.Read(&buf) || (buf.Length() > 0)) {
     LOG(LS_WARNING) << "Received invalid STUN message";
     return;
@@ -489,7 +489,7 @@
 }
 
 void TurnServer::SendStun(TurnServerConnection* conn, StunMessage* msg) {
-  rtc::ByteBuffer buf;
+  rtc::ByteBufferWriter buf;
   // Add a SOFTWARE attribute if one is set.
   if (!software_.empty()) {
     VERIFY(msg->AddAttribute(
@@ -500,7 +500,7 @@
 }
 
 void TurnServer::Send(TurnServerConnection* conn,
-                      const rtc::ByteBuffer& buf) {
+                      const rtc::ByteBufferWriter& buf) {
   rtc::PacketOptions options;
   conn->socket()->SendTo(buf.Data(), buf.Length(), conn->src(), options);
 }
@@ -794,7 +794,7 @@
   Channel* channel = FindChannel(addr);
   if (channel) {
     // There is a channel bound to this address. Send as a channel message.
-    rtc::ByteBuffer buf;
+    rtc::ByteBufferWriter buf;
     buf.WriteUInt16(channel->id());
     buf.WriteUInt16(static_cast<uint16_t>(size));
     buf.WriteBytes(data, size);
diff --git a/webrtc/p2p/base/turnserver.h b/webrtc/p2p/base/turnserver.h
index 59751a0..e520a9e 100644
--- a/webrtc/p2p/base/turnserver.h
+++ b/webrtc/p2p/base/turnserver.h
@@ -23,7 +23,7 @@
 #include "webrtc/base/socketaddress.h"
 
 namespace rtc {
-class ByteBuffer;
+class ByteBufferWriter;
 class PacketSocketFactory;
 class Thread;
 }
@@ -246,7 +246,7 @@
                                             const rtc::SocketAddress& addr);
 
   void SendStun(TurnServerConnection* conn, StunMessage* msg);
-  void Send(TurnServerConnection* conn, const rtc::ByteBuffer& buf);
+  void Send(TurnServerConnection* conn, const rtc::ByteBufferWriter& buf);
 
   void OnAllocationDestroyed(TurnServerAllocation* allocation);
   void DestroyInternalSocket(rtc::AsyncPacketSocket* socket);
diff --git a/webrtc/p2p/stunprober/stunprober.cc b/webrtc/p2p/stunprober/stunprober.cc
index 18628da..eb9a7a7 100644
--- a/webrtc/p2p/stunprober/stunprober.cc
+++ b/webrtc/p2p/stunprober/stunprober.cc
@@ -93,7 +93,7 @@
 
   // Temporary SocketAddress and buffer for RecvFrom.
   rtc::SocketAddress addr_;
-  rtc::scoped_ptr<rtc::ByteBuffer> response_packet_;
+  rtc::scoped_ptr<rtc::ByteBufferWriter> response_packet_;
 
   std::vector<Request*> requests_;
   std::vector<rtc::SocketAddress> server_ips_;
@@ -111,7 +111,7 @@
     const std::vector<rtc::SocketAddress>& server_ips)
     : prober_(prober),
       socket_(socket),
-      response_packet_(new rtc::ByteBuffer(nullptr, kMaxUdpBufferSize)),
+      response_packet_(new rtc::ByteBufferWriter(nullptr, kMaxUdpBufferSize)),
       server_ips_(server_ips),
       thread_checker_(prober->thread_checker_) {
   socket_->SignalReadPacket.connect(
@@ -140,8 +140,8 @@
       rtc::CreateRandomString(cricket::kStunTransactionIdLength));
   message.SetType(cricket::STUN_BINDING_REQUEST);
 
-  rtc::scoped_ptr<rtc::ByteBuffer> request_packet(
-      new rtc::ByteBuffer(nullptr, kMaxUdpBufferSize));
+  rtc::scoped_ptr<rtc::ByteBufferWriter> request_packet(
+      new rtc::ByteBufferWriter(nullptr, kMaxUdpBufferSize));
   if (!message.Write(request_packet.get())) {
     prober_->ReportOnFinished(WRITE_FAILED);
     return;
@@ -170,7 +170,7 @@
 void StunProber::Requester::Request::ProcessResponse(const char* buf,
                                                      size_t buf_len) {
   int64_t now = rtc::Time64();
-  rtc::ByteBuffer message(buf, buf_len);
+  rtc::ByteBufferReader message(buf, buf_len);
   cricket::StunMessage stun_response;
   if (!stun_response.Read(&message)) {
     // Invalid or incomplete STUN packet.