Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MessageParser.cpp Source File

MessageParser.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2018 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include <string.h>
00018 
00019 #include "nfc/ndef/MessageParser.h"
00020 #include "nfc/ndef/Record.h"
00021 
00022 namespace {
00023 struct buffer_iterator_t {
00024     buffer_iterator_t(const mbed::Span<const uint8_t>  &buffer) :
00025         buffer(buffer),
00026         position(0)
00027     { }
00028 
00029     uint8_t operator*()
00030     {
00031         return buffer[position];
00032     }
00033 
00034     buffer_iterator_t &operator++()
00035     {
00036         ++position;
00037         return *this;
00038     }
00039 
00040     buffer_iterator_t operator++(int)
00041     {
00042         buffer_iterator_t previous = *this;
00043         ++*this;
00044         return previous;
00045     }
00046 
00047     buffer_iterator_t &operator+=(size_t increment)
00048     {
00049         position += increment;
00050         return *this;
00051     }
00052 
00053     operator bool() const
00054     {
00055         return (position >= buffer.size()) ? false : true;
00056     }
00057 
00058     size_t remaining_size() const
00059     {
00060         return buffer.size() - position;
00061     }
00062 
00063     void read_le(uint8_t *dest, size_t size)
00064     {
00065         memcpy(dest, buffer.data() + position, size);
00066         position += size;
00067     }
00068 
00069     void read_be(uint8_t *dest, size_t size)
00070     {
00071         // TODO: Needs proper network to host function
00072         std::reverse_copy(
00073             buffer.data() + position,
00074             buffer.data() + position + size,
00075             dest
00076         );
00077         position += size;
00078     }
00079 
00080     mbed::Span<const uint8_t>  get_underlying_buffer() const
00081     {
00082         return buffer.last(buffer.size() - position);
00083     }
00084 
00085 private:
00086     mbed::Span<const uint8_t>  buffer;
00087     mbed::Span<const uint8_t>::index_type position;
00088 };
00089 
00090 } // end of anonymous namespace
00091 
00092 namespace mbed {
00093 namespace nfc {
00094 namespace ndef {
00095 
00096 struct MessageParser::parsing_state_t {
00097     parsing_state_t(const Span<const uint8_t> &data_buffer) :
00098         it(data_buffer),
00099         first_record_parsed(false),
00100         last_record_parsed(false),
00101         error(false)
00102     { }
00103 
00104     buffer_iterator_t it;
00105     bool first_record_parsed: 1;
00106     bool last_record_parsed: 1;
00107     bool error: 1;
00108 };
00109 
00110 MessageParser::MessageParser() :
00111     _delegate(NULL)
00112 { }
00113 
00114 void MessageParser::set_delegate(Delegate *delegate)
00115 {
00116     _delegate = delegate;
00117 }
00118 
00119 void MessageParser::parse(const Span<const uint8_t>  &data_buffer)
00120 {
00121     parsing_state_t parsing_state(data_buffer);
00122     report_parsing_started();
00123     while (parsing_state.it && parse_record(parsing_state));
00124     if (!parsing_state.error && !parsing_state.last_record_parsed) {
00125         report_parsing_error(MISSING_MESSAGE_END, parsing_state);
00126     }
00127     report_parsing_terminated();
00128 }
00129 
00130 bool MessageParser::parse_record(parsing_state_t &s)
00131 {
00132     if (s.error || s.last_record_parsed) {
00133         return false;
00134     }
00135 
00136     // ensure that the header can be extracted
00137     if (s.it.remaining_size() < 1) {
00138         report_parsing_error(INSUFICIENT_DATA, s);
00139         return false;
00140     }
00141 
00142     uint8_t header = *s.it++;
00143 
00144     // NOTE: report an error until the chunk parsing design is sorted out
00145     if (header & Header::chunk_flag_bit) {
00146         report_parsing_error(CHUNK_RECORD_NOT_SUPPORTED, s);
00147         return false;
00148     }
00149 
00150     // handle first record cases
00151     if (s.first_record_parsed == false) {
00152         if (header & Header::message_begin_bit) {
00153             s.first_record_parsed = true;
00154         } else {
00155             report_parsing_error(INVALID_MESSAGE_START, s);
00156             return false;
00157         }
00158     } else if (header & Header::message_begin_bit) {
00159         report_parsing_error(INVALID_MESSAGE_START, s);
00160         return false;
00161     }
00162 
00163     // handle last record
00164     if (header & Header::message_end_bit) {
00165         s.last_record_parsed = true;
00166     }
00167 
00168     // ensure their is enough space to contain the type length, payload
00169     // length and id length
00170     uint8_t lengths_size = compute_lengths_size(header);
00171     if (s.it.remaining_size() < lengths_size) {
00172         report_parsing_error(INSUFICIENT_DATA, s);
00173         return false;
00174     }
00175 
00176     // extract the various length from the message
00177     uint8_t type_length = extract_type_length(s);
00178     uint32_t payload_length = extract_payload_length(s, header);
00179     uint8_t id_length = extract_id_length(s, header);
00180 
00181     // there should be enough bytes left in the buffer
00182     if (s.it.remaining_size() < (type_length + id_length + payload_length)) {
00183         report_parsing_error(INSUFICIENT_DATA, s);
00184         return false;
00185     }
00186 
00187     // validate the Type Name Format of the header
00188     switch (header & Header::tnf_bits) {
00189         case RecordType::empty:
00190             if (type_length || payload_length || id_length) {
00191                 report_parsing_error(INVALID_EMPTY_RECORD, s);
00192                 return false;
00193             }
00194             break;
00195         case RecordType::well_known_type:
00196         case RecordType::media_type:
00197         case RecordType::absolute_uri:
00198         case RecordType::external_type:
00199             if (!type_length) {
00200                 report_parsing_error(MISSING_TYPE_VALUE, s);
00201                 return false;
00202             }
00203             break;
00204         case RecordType::unknown:
00205             if (type_length) {
00206                 report_parsing_error(INVALID_UNKNOWN_TYPE_LENGTH, s);
00207                 return false;
00208             }
00209             break;
00210         case RecordType::unchanged:
00211             // shouldn't be handled outside of chunk handling
00212             report_parsing_error(INVALID_UNCHANGED_TYPE, s);
00213             return false;
00214         default:
00215             report_parsing_error(INVALID_TYPE_NAME_FORMAT, s);
00216             return false;
00217     }
00218 
00219     // build the record
00220     Record record;
00221 
00222     // flags
00223     record.last_record = header & Header::message_end_bit;
00224 
00225     // type
00226     record.type.tnf = static_cast<RecordType::tnf_t>(header & Header::tnf_bits);
00227     if (type_length) {
00228         record.type.value = s.it.get_underlying_buffer().first(type_length);
00229         s.it += type_length;
00230     }
00231 
00232     // id
00233     if (id_length) {
00234         record.id = s.it.get_underlying_buffer().first(id_length);
00235         s.it += id_length;
00236     }
00237 
00238     // payload
00239     if (payload_length) {
00240         record.payload = s.it.get_underlying_buffer().first(payload_length);
00241         s.it += payload_length;
00242     }
00243 
00244     s.it += payload_length;
00245 
00246     report_record_parsed(record);
00247 
00248     return true;
00249 }
00250 
00251 uint8_t MessageParser::compute_lengths_size(uint8_t header)
00252 {
00253     return 1 /* type_length size */ +
00254            ((header & Header::short_record_bit) ? 1 : 4) /* payload length */ +
00255            ((header & Header::id_length_bit) ? 1 : 0);
00256 }
00257 
00258 uint8_t MessageParser::extract_type_length(parsing_state_t &s)
00259 {
00260     return *s.it++;
00261 }
00262 
00263 uint32_t MessageParser::extract_payload_length(parsing_state_t &s, uint8_t header)
00264 {
00265     uint32_t payload_length = 0;
00266     if (header & Header::short_record_bit) {
00267         payload_length = *s.it++;
00268     } else {
00269         s.it.read_be(
00270             reinterpret_cast<uint8_t *>(&payload_length),
00271             sizeof(payload_length)
00272         );
00273     }
00274     return payload_length;
00275 }
00276 
00277 uint8_t MessageParser::extract_id_length(parsing_state_t &s, uint8_t header)
00278 {
00279     return (header & Header::id_length_bit) ? *s.it++ : 0;
00280 }
00281 
00282 void MessageParser::report_parsing_started()
00283 {
00284     if (_delegate) {
00285         _delegate->on_parsing_started();
00286     }
00287 }
00288 
00289 void MessageParser::report_record_parsed(const Record &record)
00290 {
00291     if (_delegate) {
00292         _delegate->on_record_parsed(record);
00293     }
00294 }
00295 
00296 void MessageParser::report_parsing_terminated()
00297 {
00298     if (_delegate) {
00299         _delegate->on_parsing_terminated();
00300     }
00301 }
00302 
00303 void MessageParser::report_parsing_error(error_t error, parsing_state_t &parsing_state)
00304 {
00305     parsing_state.error = true;
00306     if (_delegate) {
00307         _delegate->on_parsing_error(error);
00308     }
00309 }
00310 
00311 } // namespace ndef
00312 } // namespace nfc
00313 } // namespace mbed
00314