diff options
-rw-r--r-- | components/components_tests.gyp | 4 | ||||
-rw-r--r-- | components/pairing.gypi | 7 | ||||
-rw-r--r-- | components/pairing/BUILD.gn | 14 | ||||
-rw-r--r-- | components/pairing/message_buffer.cc | 56 | ||||
-rw-r--r-- | components/pairing/message_buffer.h | 52 | ||||
-rw-r--r-- | components/pairing/message_buffer_unittest.cc | 84 |
6 files changed, 215 insertions, 2 deletions
diff --git a/components/components_tests.gyp b/components/components_tests.gyp index 6074c87..c6f9a8f 100644 --- a/components/components_tests.gyp +++ b/components/components_tests.gyp @@ -601,10 +601,14 @@ ], }], ['chromeos==1', { + 'sources': [ + 'pairing/message_buffer_unittest.cc', + ], 'sources!': [ 'storage_monitor/storage_monitor_linux_unittest.cc', ], 'dependencies': [ + 'components.gyp:pairing', '../chromeos/chromeos.gyp:chromeos_test_support', ], }], diff --git a/components/pairing.gypi b/components/pairing.gypi index b6c00ff..35f13c9 100644 --- a/components/pairing.gypi +++ b/components/pairing.gypi @@ -14,16 +14,19 @@ 'pairing_api_proto', '../base/base.gyp:base', '../device/bluetooth/bluetooth.gyp:device_bluetooth', + '../net/net.gyp:net', ], 'sources': [ + 'pairing/controller_pairing_controller.cc', + 'pairing/controller_pairing_controller.h', 'pairing/fake_controller_pairing_controller.cc', 'pairing/fake_controller_pairing_controller.h', 'pairing/fake_host_pairing_controller.cc', 'pairing/fake_host_pairing_controller.h', - 'pairing/controller_pairing_controller.cc', - 'pairing/controller_pairing_controller.h', 'pairing/host_pairing_controller.cc', 'pairing/host_pairing_controller.h', + 'pairing/message_buffer.cc', + 'pairing/message_buffer.h', ], }, { diff --git a/components/pairing/BUILD.gn b/components/pairing/BUILD.gn index af7b979..55f29ed 100644 --- a/components/pairing/BUILD.gn +++ b/components/pairing/BUILD.gn @@ -14,11 +14,25 @@ source_set("pairing") { "pairing/controller_pairing_controller.h", "pairing/host_pairing_controller.cc", "pairing/host_pairing_controller.h", + "pairing/message_buffer.cc", + "pairing/message_buffer.h", ] deps = [ "//base", "//device/bluetooth", + "//net", + ] +} + +source_set("unit_tests") { + sources = [ + "message_buffer_unittest.cc", + ] + + deps = [ + ":pairing", + "//testing/gtest", ] } diff --git a/components/pairing/message_buffer.cc b/components/pairing/message_buffer.cc new file mode 100644 index 0000000..3cfe95d --- /dev/null +++ b/components/pairing/message_buffer.cc @@ -0,0 +1,56 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/pairing/message_buffer.h" + +#include "net/base/io_buffer.h" + +namespace pairing_chromeos { + +MessageBuffer::MessageBuffer() + : buffer_offset_(0), + total_buffer_size_(0) { +} + +MessageBuffer::~MessageBuffer() {} + +int MessageBuffer::AvailableBytes() { + return total_buffer_size_ - buffer_offset_; +} + +void MessageBuffer::ReadBytes(char* buffer, int size) { + CHECK_LE(size, AvailableBytes()); + + int offset = 0; + while (offset < size) { + scoped_refptr<net::IOBuffer> io_buffer = pending_data_.front().first; + int io_buffer_size = pending_data_.front().second; + + CHECK_GT(io_buffer_size, buffer_offset_); + int copy_size = std::min(size - offset, io_buffer_size - buffer_offset_); + memcpy(&buffer[offset], &io_buffer->data()[buffer_offset_], copy_size); + + offset += copy_size; + buffer_offset_ += copy_size; + + CHECK_LE(buffer_offset_, io_buffer_size); + if (buffer_offset_ == io_buffer_size) { + CHECK_GE(total_buffer_size_, io_buffer_size); + total_buffer_size_ -= io_buffer_size; + pending_data_.pop_front(); + buffer_offset_ = 0; + } + } + CHECK_EQ(offset, size); +} + +void MessageBuffer::AddIOBuffer(scoped_refptr<net::IOBuffer> io_buffer, + int size) { + if (size == 0) + return; + pending_data_.push_back(std::make_pair(io_buffer, size)); + total_buffer_size_ += size; +} + +} // namespace pairing_chromeos diff --git a/components/pairing/message_buffer.h b/components/pairing/message_buffer.h new file mode 100644 index 0000000..8b2fcc0 --- /dev/null +++ b/components/pairing/message_buffer.h @@ -0,0 +1,52 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PAIRING_MESSAGE_BUFFER_H_ +#define COMPONENTS_PAIRING_MESSAGE_BUFFER_H_ + +#include <deque> + +#include "base/logging.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" + +namespace net { +class IOBuffer; +} + +namespace pairing_chromeos { + +// A MessageBuffer is a simple wrapper around an ordered set of buffers received +// from a socket. It keeps track of the amount of unread data, and allows data +// to be retreived that was split across buffers in a single chunk. +class MessageBuffer { + public: + MessageBuffer(); + ~MessageBuffer(); + + // Returns the number of bytes currently received, but not yet read. + int AvailableBytes(); + + // Read |size| bytes into |buffer|. |size| must be smaller than or equal to + // the current number of available bytes. + void ReadBytes(char* buffer, int size); + + // Add the data from an IOBuffer. A reference to the IOBuffer will be + // maintained until it is drained. + void AddIOBuffer(scoped_refptr<net::IOBuffer> io_buffer, int size); + + private: + // Offset of the next byte to be read from the current IOBuffer. + int buffer_offset_; + // Total number of bytes in IOBuffers in |pending_data_|, including bytes that + // have already been read. + int total_buffer_size_; + std::deque<std::pair<scoped_refptr<net::IOBuffer>, int> > pending_data_; + + DISALLOW_COPY_AND_ASSIGN(MessageBuffer); +}; + +} // namespace pairing_chromeos + +#endif // COMPONENTS_PAIRING_MESSAGE_BUFFER_H_ diff --git a/components/pairing/message_buffer_unittest.cc b/components/pairing/message_buffer_unittest.cc new file mode 100644 index 0000000..2f9fe40 --- /dev/null +++ b/components/pairing/message_buffer_unittest.cc @@ -0,0 +1,84 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/pairing/message_buffer.h" + +#include "net/base/io_buffer.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace pairing_chromeos { + +typedef testing::Test MessageBufferTest; + +TEST_F(MessageBufferTest, BasicReadWrite) { + MessageBuffer message_buffer; + scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(3)); + io_buffer->data()[0] = 3; + io_buffer->data()[1] = 1; + io_buffer->data()[2] = 4; + + message_buffer.AddIOBuffer(io_buffer, 3); + + EXPECT_EQ(message_buffer.AvailableBytes(), 3); + char data = 0; + message_buffer.ReadBytes(&data, 1); + EXPECT_EQ(data, 3); + EXPECT_EQ(message_buffer.AvailableBytes(), 2); + message_buffer.ReadBytes(&data, 1); + EXPECT_EQ(data, 1); + EXPECT_EQ(message_buffer.AvailableBytes(), 1); + message_buffer.ReadBytes(&data, 1); + EXPECT_EQ(data, 4); + EXPECT_EQ(message_buffer.AvailableBytes(), 0); +} + +TEST_F(MessageBufferTest, SplitBuffer) { + MessageBuffer message_buffer; + scoped_refptr<net::IOBuffer> io_buffer0(new net::IOBuffer(1)); + io_buffer0->data()[0] = 3; + + scoped_refptr<net::IOBuffer> io_buffer1(new net::IOBuffer(2)); + io_buffer1->data()[0] = 1; + io_buffer1->data()[1] = 4; + + message_buffer.AddIOBuffer(io_buffer0, 1); + message_buffer.AddIOBuffer(io_buffer1, 2); + + EXPECT_EQ(message_buffer.AvailableBytes(), 3); + char data[3]; + message_buffer.ReadBytes(data, 3); + EXPECT_EQ(message_buffer.AvailableBytes(), 0); + EXPECT_EQ(data[0], 3); + EXPECT_EQ(data[1], 1); + EXPECT_EQ(data[2], 4); +} + +TEST_F(MessageBufferTest, EmptyBuffer) { + MessageBuffer message_buffer; + scoped_refptr<net::IOBuffer> io_buffer0(new net::IOBuffer(1)); + io_buffer0->data()[0] = 3; + + scoped_refptr<net::IOBuffer> io_buffer1(new net::IOBuffer(0)); + scoped_refptr<net::IOBuffer> io_buffer2(new net::IOBuffer(2)); + io_buffer2->data()[0] = 1; + io_buffer2->data()[1] = 4; + + message_buffer.AddIOBuffer(io_buffer0, 1); + message_buffer.AddIOBuffer(io_buffer1, 0); + message_buffer.AddIOBuffer(io_buffer2, 2); + + EXPECT_EQ(message_buffer.AvailableBytes(), 3); + char data = 0; + message_buffer.ReadBytes(&data, 1); + EXPECT_EQ(data, 3); + EXPECT_EQ(message_buffer.AvailableBytes(), 2); + message_buffer.ReadBytes(&data, 1); + EXPECT_EQ(data, 1); + EXPECT_EQ(message_buffer.AvailableBytes(), 1); + message_buffer.ReadBytes(&data, 1); + EXPECT_EQ(data, 4); + EXPECT_EQ(message_buffer.AvailableBytes(), 0); +} + +} // namespace pairing_chromeos |