Home | History | Annotate | Download | only in nanotool
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "nanopacket.h"
     18 
     19 namespace android {
     20 
     21 constexpr uint8_t kSyncByte(0x31);
     22 
     23 // CRC constants.
     24 constexpr uint32_t kInitialCrc(0xffffffff);
     25 constexpr uint32_t kCrcTable[] = {
     26     0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
     27     0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
     28     0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
     29     0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
     30 };
     31 
     32 // Computes the CRC of one word.
     33 uint32_t Crc32Word(uint32_t crc, uint32_t data, int cnt) {
     34     crc = crc ^ data;
     35 
     36     for (int i = 0; i < cnt; i++) {
     37         crc = (crc << 4) ^ kCrcTable[crc >> 28];
     38     }
     39 
     40     return crc;
     41 }
     42 
     43 // Computes the CRC32 of a buffer given a starting CRC.
     44 uint32_t Crc32(const uint8_t *buffer, int length) {
     45     int i;
     46     uint32_t crc = kInitialCrc;
     47 
     48     // Word by word crc32
     49     for (i = 0; i < (length >> 2); i++) {
     50         crc = Crc32Word(crc, ((uint32_t *)buffer)[i], 8);
     51     }
     52 
     53     // Zero pad last word if required.
     54     if (length & 0x3) {
     55         uint32_t word = 0;
     56 
     57         for (i*=4; i<length; i++) {
     58             word |= buffer[i] << ((i & 0x3) * 8);
     59         }
     60 
     61         crc = Crc32Word(crc, word, 8);
     62     }
     63 
     64     return crc;
     65 }
     66 
     67 NanoPacket::NanoPacket(uint32_t sequence_number, PacketReason reason,
     68         const std::vector<uint8_t> *data) {
     69     Reset();
     70     parsing_state_ = ParsingState::Complete;
     71     sequence_number_ = sequence_number;
     72     reason_ = static_cast<uint32_t>(reason);
     73 
     74     // Resize the buffer to accomodate header, footer and data content.
     75     size_t data_size = data ? data->size() : 0;
     76     size_t required_buffer_size = 14 + data_size;
     77     if (packet_buffer_.size() < required_buffer_size) {
     78         packet_buffer_.resize(required_buffer_size);
     79     }
     80 
     81     if (packet_content_.size() < required_buffer_size) {
     82         packet_content_.resize(required_buffer_size);
     83     }
     84 
     85     // Format the header of the packet.
     86     packet_buffer_[0] = kSyncByte;
     87     packet_buffer_[1] = sequence_number;
     88     packet_buffer_[2] = sequence_number >> 8;
     89     packet_buffer_[3] = sequence_number >> 16;
     90     packet_buffer_[4] = sequence_number >> 24;
     91     packet_buffer_[5] = static_cast<uint32_t>(reason);
     92     packet_buffer_[6] = static_cast<uint32_t>(reason) >> 8;
     93     packet_buffer_[7] = static_cast<uint32_t>(reason) >> 16;
     94     packet_buffer_[8] = static_cast<uint32_t>(reason) >> 24;
     95     packet_buffer_[9] = data_size;
     96 
     97     // Insert the data content of the packet.
     98     if (data) {
     99         std::copy(data->begin(), data->end(), packet_buffer_.begin() + 10);
    100         std::copy(data->begin(), data->end(), packet_content_.begin());
    101     }
    102 
    103     // Format the CRC footer.
    104     uint32_t crc = Crc32(packet_buffer_.data(), required_buffer_size - 4);
    105     packet_buffer_[data_size + 10] = crc;
    106     packet_buffer_[data_size + 11] = crc >> 8;
    107     packet_buffer_[data_size + 12] = crc >> 16;
    108     packet_buffer_[data_size + 13] = crc >> 24;
    109 }
    110 
    111 NanoPacket::NanoPacket() {
    112     Reset();
    113 }
    114 
    115 void NanoPacket::Reset() {
    116     packet_buffer_.clear();
    117     parsing_state_ = ParsingState::Idle;
    118     parsing_progress_ = 0;
    119     sequence_number_ = 0;
    120     reason_ = 0;
    121     packet_content_.clear();
    122     crc_ = 0;
    123 }
    124 
    125 bool NanoPacket::ParsingIsComplete() const {
    126     return parsing_state_ == ParsingState::Complete;
    127 }
    128 
    129 const std::vector<uint8_t>& NanoPacket::packet_buffer() const {
    130     return packet_buffer_;
    131 }
    132 
    133 uint32_t NanoPacket::reason() const {
    134     return reason_;
    135 }
    136 
    137 PacketReason NanoPacket::TypedReason() const {
    138     return static_cast<PacketReason>(reason_);
    139 }
    140 
    141 const std::vector<uint8_t>& NanoPacket::packet_content() const {
    142     return packet_content_;
    143 }
    144 
    145 NanoPacket::ParseResult NanoPacket::Parse(uint8_t *buffer, size_t length,
    146         size_t *bytes_parsed) {
    147     for (size_t i = 0; i < length; i++) {
    148         // Once the state machine is not idle, save all bytes to the current
    149         // packet to allow CRC to be computed at the end.
    150         if (parsing_state_ != ParsingState::Idle) {
    151             packet_buffer_.push_back(buffer[i]);
    152         }
    153 
    154         // Proceed through the various states of protocol parsing.
    155         if (parsing_state_ == ParsingState::Idle && buffer[i] == kSyncByte) {
    156             packet_buffer_.push_back(buffer[i]);
    157             parsing_state_ = ParsingState::ParsingSequenceNumber;
    158         } else if (parsing_state_ == ParsingState::ParsingSequenceNumber
    159                 && DeserializeWord(&sequence_number_, buffer[i])) {
    160             parsing_state_ = ParsingState::ParsingReason;
    161         } else if (parsing_state_ == ParsingState::ParsingReason
    162                 && DeserializeWord(&reason_, buffer[i])) {
    163             parsing_state_ = ParsingState::ParsingLength;
    164         } else if (parsing_state_ == ParsingState::ParsingLength) {
    165             uint8_t length = buffer[i];
    166             if (length > 0) {
    167                 packet_content_.resize(buffer[i]);
    168                 parsing_state_ = ParsingState::ParsingContent;
    169             } else {
    170                 parsing_state_ = ParsingState::ParsingCrc;
    171             }
    172         } else if (parsing_state_ == ParsingState::ParsingContent) {
    173             packet_content_[parsing_progress_++] = buffer[i];
    174 
    175             if (parsing_progress_ == packet_content_.size()) {
    176                 parsing_progress_ = 0;
    177                 parsing_state_ = ParsingState::ParsingCrc;
    178             }
    179         } else if (parsing_state_ == ParsingState::ParsingCrc
    180                 && DeserializeWord(&crc_, buffer[i])) {
    181             *bytes_parsed = i + 1;
    182             if (ValidateCrc()) {
    183                 parsing_state_ = ParsingState::Complete;
    184                 return ParseResult::Success;
    185             } else {
    186                 return ParseResult::CrcMismatch;
    187             }
    188         }
    189     }
    190 
    191     *bytes_parsed = length;
    192     return ParseResult::Incomplete;
    193 }
    194 
    195 bool NanoPacket::ValidateCrc() {
    196     size_t crc_length = packet_buffer_.size() - 4;
    197     uint32_t computed_crc = Crc32(packet_buffer_.data(), crc_length);
    198 
    199     if (computed_crc != crc_) {
    200         Reset();
    201         return false;
    202     }
    203 
    204     return true;
    205 }
    206 
    207 }  // namespace android
    208