Kenji Arai / TYBLE16_mbedlized_os5_several_examples_1st

Dependencies:   nRF51_Vdd TextLCD BME280

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MessageBuilder.cpp Source File

MessageBuilder.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/MessageBuilder.h"
00020 
00021 namespace mbed {
00022 namespace nfc {
00023 namespace ndef {
00024 
00025 MessageBuilder::MessageBuilder(const Span<uint8_t>  &buffer) :
00026     _message_buffer(buffer),
00027     _position(0),
00028     _message_started(false),
00029     _message_ended(false),
00030     _in_chunk(false)
00031 { }
00032 
00033 bool MessageBuilder::append_record(
00034     const RecordType &type,
00035     const RecordPayload  &payload,
00036     bool is_last_record
00037 )
00038 {
00039     Record record(
00040         type,
00041         payload,
00042         /* id */ RecordID(),
00043         /* chunk */ false,
00044         is_last_record
00045     );
00046 
00047     return append_record(record);
00048 }
00049 
00050 bool MessageBuilder::append_record(
00051     const RecordType &type,
00052     const PayloadBuilder &builder,
00053     bool is_last_record
00054 )
00055 {
00056     Record record(
00057         type,
00058         RecordPayload(),
00059         RecordID(),
00060         /* chunk */ false,
00061         is_last_record
00062     );
00063 
00064     return append_record(record, &builder);
00065 }
00066 
00067 
00068 bool MessageBuilder::append_record(const Record &record, const PayloadBuilder *builder)
00069 {
00070     if (_message_ended) {
00071         return false;
00072     }
00073 
00074     if (record.type.value.size() > 255) {
00075         return false;
00076     }
00077 
00078     if (record.id.size() > 255) {
00079         return false;
00080     }
00081 
00082     if (!record.id.empty() && _in_chunk) {
00083         if (record.chunk) {
00084             // middle chunk
00085             return false;
00086         } else if (record.type.tnf == RecordType::unchanged) {
00087             // terminating chunk
00088             return false;
00089         }
00090     }
00091 
00092     if (_in_chunk && record.type.tnf != RecordType::unchanged) {
00093         return false;
00094     }
00095 
00096     if (!_in_chunk && record.chunk && record.type.tnf == RecordType::unchanged) {
00097         return false;
00098     }
00099 
00100     if (record.type.tnf == RecordType::empty) {
00101         if (!record.type.value.empty()) {
00102             return false;
00103         }
00104 
00105         if (!record.id.empty()) {
00106             return false;
00107         }
00108 
00109         if (get_payload_size(record, builder)) {
00110             return false;
00111         }
00112     }
00113 
00114     if (record.type.tnf == RecordType::well_known_type ||
00115             record.type.tnf == RecordType::media_type ||
00116             record.type.tnf == RecordType::absolute_uri ||
00117             record.type.tnf == RecordType::external_type
00118        ) {
00119         if (record.type.value.empty()) {
00120             return false;
00121         }
00122     }
00123 
00124     if (record.type.tnf == RecordType::unknown && !record.type.value.empty()) {
00125         return false;
00126     }
00127 
00128     size_t record_size = compute_record_size(record, builder);
00129     if (record_size > (_message_buffer.size() - _position)) {
00130         return false;
00131     }
00132 
00133     append_header(record, builder);
00134     append_type_length(record);
00135     append_payload_length(record, builder);
00136     append_id_length(record);
00137     append_type(record);
00138     append_id(record);
00139     append_payload(record, builder);
00140 
00141     if (record.chunk) {
00142         _in_chunk = true;
00143     } else if (record.type.tnf == RecordType::unchanged) {
00144         // last chunk reached
00145         _in_chunk = false;
00146     }
00147 
00148     return true;
00149 }
00150 
00151 void MessageBuilder::reset()
00152 {
00153     _position = 0;
00154     _message_started = false;
00155     _message_ended = false;
00156     _in_chunk = false;
00157 }
00158 
00159 void MessageBuilder::reset(const Span<uint8_t>  &buffer)
00160 {
00161     _message_buffer = buffer;
00162     _position = 0;
00163     _message_started = false;
00164     _message_ended = false;
00165     _in_chunk = false;
00166 }
00167 
00168 bool MessageBuilder::is_message_complete() const
00169 {
00170     return _message_ended;
00171 }
00172 
00173 Span<const uint8_t>  MessageBuilder::get_message() const
00174 {
00175     if (is_message_complete()) {
00176         return _message_buffer.first(_position);
00177     } else {
00178         return Span<const uint8_t> ();
00179     }
00180 }
00181 
00182 size_t MessageBuilder::compute_record_size(const Record &record, const PayloadBuilder *builder)
00183 {
00184     size_t record_size = 0;
00185     record_size = 1; /* header */
00186     record_size += 1; /* type length */
00187     record_size += is_short_payload(record, builder) ? 1 : 4;
00188 
00189     if (!record.id.empty()) {
00190         record_size += 1;
00191     }
00192 
00193     record_size += record.type.value.size();
00194     record_size += record.id.size();
00195     record_size += get_payload_size(record, builder);
00196 
00197     return record_size;
00198 }
00199 
00200 void MessageBuilder::append_header(const Record &record, const PayloadBuilder *builder)
00201 {
00202     uint8_t header = 0;
00203     if (!_message_started) {
00204         header |= Header::message_begin_bit;
00205         _message_started = true;
00206     }
00207 
00208     if (record.last_record) {
00209         header |= Header::message_end_bit;
00210         _message_ended = true;
00211     }
00212 
00213     if (record.chunk) {
00214         header |= Header::chunk_flag_bit;
00215     }
00216 
00217     if (is_short_payload(record, builder)) {
00218         header |= Header::short_record_bit;
00219     }
00220 
00221     if (record.id.size()) {
00222         header |= Header::id_length_bit;
00223     }
00224 
00225     header |= record.type.tnf;
00226     _message_buffer[_position++] = header;
00227 }
00228 
00229 void MessageBuilder::append_type_length(const Record &record)
00230 {
00231     _message_buffer[_position++] = record.type.value.size();
00232 }
00233 
00234 void MessageBuilder::append_payload_length(const Record &record, const PayloadBuilder *builder)
00235 {
00236     size_t size = get_payload_size(record, builder);
00237 
00238     if (is_short_payload(record, builder)) {
00239         _message_buffer[_position++] = size;
00240     } else {
00241         _message_buffer[_position++] = (size >> 24) & 0xFF;
00242         _message_buffer[_position++] = (size >> 16) & 0xFF;
00243         _message_buffer[_position++] = (size >> 8) & 0xFF;
00244         _message_buffer[_position++] = size & 0xFF;
00245     }
00246 }
00247 
00248 void MessageBuilder::append_id_length(const Record &record)
00249 {
00250     if (record.id.empty()) {
00251         return;
00252     }
00253 
00254     _message_buffer[_position++] = record.id.size();
00255 }
00256 
00257 void MessageBuilder::append_type(const Record &record)
00258 {
00259     if (record.type.value.empty()) {
00260         return;
00261     }
00262 
00263     memcpy(
00264         _message_buffer.data() + _position,
00265         record.type.value.data(),
00266         record.type.value.size()
00267     );
00268     _position += record.type.value.size();
00269 }
00270 
00271 void MessageBuilder::append_id(const Record &record)
00272 {
00273     if (record.id.empty()) {
00274         return;
00275     }
00276 
00277     memcpy(
00278         _message_buffer.data() + _position,
00279         record.id.data(),
00280         record.id.size()
00281     );
00282     _position += record.id.size();
00283 }
00284 
00285 void MessageBuilder::append_payload(const Record &record, const PayloadBuilder *builder)
00286 {
00287     size_t size = get_payload_size(record, builder);
00288     if (!size) {
00289         return;
00290     }
00291 
00292     if (builder) {
00293         builder->build(_message_buffer.subspan(_position, size));
00294     } else {
00295         memcpy(
00296             _message_buffer.data() + _position,
00297             record.payload.data(),
00298             size
00299         );
00300     }
00301 
00302     _position += size;
00303 }
00304 
00305 bool MessageBuilder::is_short_payload(const Record &record, const PayloadBuilder *builder)
00306 {
00307     if (get_payload_size(record, builder) <= 255) {
00308         return true;
00309     } else {
00310         return false;
00311     }
00312 }
00313 
00314 size_t MessageBuilder::get_payload_size(const Record &record, const PayloadBuilder *builder)
00315 {
00316     return builder ? builder->size() : record.payload.size();
00317 }
00318 
00319 } // namespace ndef
00320 } // namespace nfc
00321 } // namespace mbed
00322