Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
Generated on Tue Aug 9 2022 00:37:15 by
1.7.2