blob: 8a8c591eed014b70c32cc163c60395d11f37622a [file] [log] [blame]
/******************************************************************************
*
* Copyright (C) 2017 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
#pragma once
#include <cstdint>
#include <iterator>
#include <vector>
namespace test_vendor_lib {
// Abstract representation of an SDU packet that contains an L2CAP
// payload. This class is meant to be used in collaboration with
// the L2cap class defined in l2cap.h. For example, an SDU packet
// may look as follows:
//
// vector<uint8_t> sdu = {0x04, 0x00, 0x48, 0x00, 0x04, 0x00, 0xab,
// 0xcd, 0x78, 0x56}
//
// The first two bytes (in little endian) should be read as 0x0004
// and is the length of the payload of the SDU packet.
//
// The next two bytes (also in little endian) are the channel ID
// and should be read as 0x0048. These should remain the same for
// any number of SDUs that are a part of the same packet stream.
//
// Following the CID bytes, are the total length bytes. Since this
// SDU only requires a single packet, the length here is the same
// as the length in the first two bytes of the packet. Again stored
// in little endian.
//
// Next comes the two control bytes. These begin the L2CAP payload
// of the SDU packet; however, they will not be added to the L2CAP
// packet that is being constructed in the assemble function that
// will be creating an L2CAP packet from a stream of L2capSdu
// objects.
//
// The final two bytes are the frame check sequence that should be
// calculated from the start of the vector to the end of the
// payload.
//
// Thus, calling assemble on this example would create a
// zero-length L2CAP packet because the information payload of the
// L2CAP packet will not include either of the control or FCS
// bytes.
//
class L2capSdu {
public:
// Returns a completed L2capSdu object.
L2capSdu(std::vector<uint8_t> create_from);
static L2capSdu L2capSduBuilder(std::vector<uint8_t> create_from);
// TODO: Remove this when the move to L2capSdu* is done
L2capSdu& operator=(L2capSdu obj1) {
sdu_data_.clear();
sdu_data_ = obj1.sdu_data_;
return *this;
}
// Get a vector iterator that points to the first byte of the
// L2CAP payload within an SDU. The offset parameter will be the
// number of bytes that are in the SDU header. This should always
// be 6 bytes with the exception being the first SDU of a stream
// of SDU packets where the first SDU packet will have an extra
// two bytes and the offset should be 8 bytes.
std::vector<uint8_t>::const_iterator get_payload_begin(
const unsigned int offset) const;
// Get a vector iterator that points to the last bytes of the
// L2CAP payload within an SDU packet. There is no offset
// parameter for this function because there will always be two
// FCS bytes and nothing else at the end of each SDU.
std::vector<uint8_t>::const_iterator get_payload_end() const;
// Get the FCS bytes from the end of the L2CAP payload of an SDU
// packet.
uint16_t get_fcs() const;
uint16_t get_payload_length() const;
uint16_t calculate_fcs() const;
// Get the two control bytes that begin the L2CAP payload. These
// bytes will contain information such as the Segmentation and
// Reassembly bits, and the TxSeq/ReqSeq numbers.
uint16_t get_controls() const;
uint16_t get_total_l2cap_length() const;
size_t get_vector_size() const;
uint16_t get_channel_id() const;
// Returns true if the SDU control sequence for Segmentation and
// Reassembly is 00b, false otherwise.
static bool is_complete_l2cap(const L2capSdu& sdu);
// Returns true if the SDU control sequence for Segmentation and
// Reassembly is 01b, false otherwise.
static bool is_starting_sdu(const L2capSdu& sdu);
// Returns true if the SDU control sequence for Segmentation and
// Reasembly is 10b, false otherwise.
static bool is_ending_sdu(const L2capSdu& sdu);
private:
// This is the SDU packet in bytes.
std::vector<uint8_t> sdu_data_;
// Table for precalculated lfsr values.
static const uint16_t lfsr_table_[256];
uint16_t convert_from_little_endian(const unsigned int starting_index) const;
}; // L2capSdu
} // namespace test_vendor_lib