Chromium Code Reviews| Index: device/u2f/u2f_message.cc |
| diff --git a/device/u2f/u2f_message.cc b/device/u2f/u2f_message.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..aaba8ad4262f1f3bbb2912dfb1466206fa962771 |
| --- /dev/null |
| +++ b/device/u2f/u2f_message.cc |
| @@ -0,0 +1,142 @@ |
| +// Copyright 2016 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 "device/u2f/u2f_message.h" |
| +#include "device/u2f/u2f_packet.h" |
| + |
| +namespace device { |
| + |
| +// static |
| +scoped_refptr<U2fMessage> U2fMessage::Create( |
| + const uint8_t channel_id[U2fPacket::kChannelIdSize], |
| + const Type type, |
| + const std::vector<uint8_t>& data) { |
| + if (data.size() > kMaxMessageSize) |
| + return nullptr; |
| + |
| + return make_scoped_refptr(new U2fMessage(channel_id, type, data)); |
| +} |
| + |
| +// static |
| +scoped_refptr<U2fMessage> U2fMessage::Create( |
| + scoped_refptr<net::IOBufferWithSize> buf) { |
| + if (buf == nullptr || |
| + static_cast<size_t>(buf->size()) > U2fPacket::kPacketSize || |
| + static_cast<size_t>(buf->size()) < kInitPacketHeader) |
| + return nullptr; |
| + |
| + return make_scoped_refptr(new U2fMessage(buf)); |
| +} |
| + |
| +U2fMessage::U2fMessage(scoped_refptr<net::IOBufferWithSize> buf) |
| + : packets_(), remaining_size_(0) { |
| + scoped_refptr<U2fInitPacket> init_packet = |
| + U2fInitPacket::Create(buf, &remaining_size_); |
| + for (size_t i = 0; i < U2fPacket::kChannelIdSize; i++) |
| + channel_id_[i] = init_packet->GetChannelId()[i]; |
| + |
| + packets_.push_back(init_packet); |
| +} |
| + |
| +U2fMessage::U2fMessage(const uint8_t channel_id[U2fPacket::kChannelIdSize], |
| + const Type type, |
| + const std::vector<uint8_t>& data) |
| + : packets_(), remaining_size_() { |
| + remaining_size_ = data.size(); |
| + uint8_t sequence = 0; |
| + for (size_t i = 0; i < U2fPacket::kChannelIdSize; i++) |
| + channel_id_[i] = channel_id[i]; |
| + |
| + std::vector<uint8_t>::const_iterator first = data.begin(); |
| + std::vector<uint8_t>::const_iterator last; |
| + |
| + if (remaining_size_ > kInitPacketDataSize) { |
| + last = data.begin() + kInitPacketDataSize; |
| + remaining_size_ -= kInitPacketDataSize; |
| + } else { |
| + last = data.begin() + remaining_size_; |
| + remaining_size_ = 0; |
| + } |
| + |
| + packets_.push_back(make_scoped_refptr( |
| + new U2fInitPacket(channel_id, static_cast<uint8_t>(type), |
| + std::vector<uint8_t>(first, last), data.size()))); |
| + |
| + while (remaining_size_ > 0) { |
| + first = last; |
| + if (remaining_size_ > kContPacketDataSize) { |
| + last = first + kContPacketDataSize; |
| + remaining_size_ -= kContPacketDataSize; |
| + } else { |
| + last = first + remaining_size_; |
| + remaining_size_ = 0; |
| + } |
| + |
| + packets_.push_back(make_scoped_refptr(new U2fContPacket( |
| + channel_id, sequence, std::vector<uint8_t>(first, last)))); |
| + sequence++; |
| + } |
| +} |
| + |
| +U2fMessage::~U2fMessage() {} |
| + |
| +std::list<scoped_refptr<U2fPacket>>::const_iterator U2fMessage::begin() { |
| + return packets_.cbegin(); |
| +} |
| + |
| +std::list<scoped_refptr<U2fPacket>>::const_iterator U2fMessage::end() { |
| + return packets_.cend(); |
| +} |
| + |
| +const uint8_t* U2fMessage::GetChannelId() { |
| + return channel_id_; |
| +} |
| + |
| +scoped_refptr<net::IOBufferWithSize> U2fMessage::PopNextPacket() { |
| + if (NumPackets() > 0) { |
| + scoped_refptr<net::IOBufferWithSize> buf = packets_.front()->GetBuffer(); |
| + packets_.pop_front(); |
| + return buf; |
| + } |
| + return nullptr; |
| +} |
| + |
| +bool U2fMessage::AddContPacket(scoped_refptr<net::IOBufferWithSize> buf) { |
| + size_t remaining_size = remaining_size_; |
| + scoped_refptr<U2fContPacket> cont_packet = |
| + U2fContPacket::Create(buf, &remaining_size_); |
| + |
| + // Reject packets with a different channel id |
| + if (!std::equal(channel_id_, channel_id_ + U2fPacket::kChannelIdSize, |
| + cont_packet->GetChannelId())) { |
| + remaining_size_ = remaining_size; |
| + return false; |
| + } |
| + |
| + packets_.push_back(cont_packet); |
| + return true; |
| +} |
| + |
| +bool U2fMessage::MessageComplete() { |
| + return remaining_size_ == 0; |
| +} |
| + |
| +const std::vector<uint8_t> U2fMessage::GetData() { |
| + std::vector<uint8_t> data; |
| + |
| + for (std::list<scoped_refptr<U2fPacket>>::const_iterator it = begin(); |
| + it != end(); ++it) { |
|
Reilly Grant (use Gerrit)
2016/12/07 22:33:48
Since this is internal I would just use for (const
Casey Piper
2016/12/09 00:15:54
Done.
|
| + std::vector<uint8_t> packet_data = (*it)->GetData(); |
| + |
| + data.insert(std::end(data), packet_data.cbegin(), packet_data.cend()); |
| + } |
| + |
| + return data; |
| +} |
| + |
| +size_t U2fMessage::NumPackets() { |
| + return packets_.size(); |
| +} |
| + |
| +} // namespace device |