/src/mosquitto/libcommon/property_common.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | Copyright (c) 2018-2021 Roger Light <roger@atchoo.org> |
3 | | |
4 | | All rights reserved. This program and the accompanying materials |
5 | | are made available under the terms of the Eclipse Public License 2.0 |
6 | | and Eclipse Distribution License v1.0 which accompany this distribution. |
7 | | |
8 | | The Eclipse Public License is available at |
9 | | https://www.eclipse.org/legal/epl-2.0/ |
10 | | and the Eclipse Distribution License is available at |
11 | | http://www.eclipse.org/org/documents/edl-v10.php. |
12 | | |
13 | | SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
14 | | |
15 | | Contributors: |
16 | | Roger Light - initial implementation and documentation. |
17 | | */ |
18 | | |
19 | | #include "config.h" |
20 | | |
21 | | #include <errno.h> |
22 | | #include <stdlib.h> |
23 | | #include <string.h> |
24 | | |
25 | | #ifndef WIN32 |
26 | | # include <strings.h> |
27 | | #endif |
28 | | |
29 | | #include "mosquitto.h" |
30 | | #include "property_common.h" |
31 | | |
32 | | |
33 | | void mosquitto_property_free(mosquitto_property **property) |
34 | 25.7M | { |
35 | 25.7M | if(!property || !(*property)) return; |
36 | | |
37 | 25.7M | switch((*property)->property_type){ |
38 | 958k | case MQTT_PROP_TYPE_STRING: |
39 | 958k | mosquitto_FREE((*property)->value.s.v); |
40 | 958k | break; |
41 | | |
42 | 1.81M | case MQTT_PROP_TYPE_BINARY: |
43 | 1.81M | mosquitto_FREE((*property)->value.bin.v); |
44 | 1.81M | break; |
45 | | |
46 | 14.3k | case MQTT_PROP_TYPE_STRING_PAIR: |
47 | 14.3k | mosquitto_FREE((*property)->name.v); |
48 | 14.3k | mosquitto_FREE((*property)->value.s.v); |
49 | 14.3k | break; |
50 | | |
51 | 18.9M | case MQTT_PROP_TYPE_BYTE: |
52 | 20.9M | case MQTT_PROP_TYPE_INT16: |
53 | 21.6M | case MQTT_PROP_TYPE_INT32: |
54 | 23.0M | case MQTT_PROP_TYPE_VARINT: |
55 | | /* Nothing to free */ |
56 | 23.0M | break; |
57 | 25.7M | } |
58 | | |
59 | 25.7M | mosquitto_FREE(*property); |
60 | 25.7M | } |
61 | | |
62 | | |
63 | | BROKER_EXPORT void mosquitto_property_free_all(mosquitto_property **property) |
64 | 296k | { |
65 | 296k | mosquitto_property *p, *next; |
66 | | |
67 | 296k | if(!property) return; |
68 | | |
69 | 296k | p = *property; |
70 | 26.0M | while(p){ |
71 | 25.7M | next = p->next; |
72 | 25.7M | mosquitto_property_free(&p); |
73 | 25.7M | p = next; |
74 | 25.7M | } |
75 | 296k | *property = NULL; |
76 | 296k | } |
77 | | |
78 | | |
79 | | unsigned int mosquitto_property_get_length(const mosquitto_property *property) |
80 | 1.98k | { |
81 | 1.98k | if(!property) return 0; |
82 | | |
83 | 1.98k | switch(property->property_type){ |
84 | 1.98k | case MQTT_PROP_TYPE_BYTE: |
85 | 1.98k | return 2; /* 1 (identifier) + 1 byte */ |
86 | | |
87 | 0 | case MQTT_PROP_TYPE_INT16: |
88 | 0 | return 3; /* 1 (identifier) + 2 bytes */ |
89 | | |
90 | 0 | case MQTT_PROP_TYPE_INT32: |
91 | 0 | return 5; /* 1 (identifier) + 4 bytes */ |
92 | | |
93 | 0 | case MQTT_PROP_TYPE_VARINT: |
94 | 0 | if(property->value.varint < 128){ |
95 | 0 | return 2; |
96 | 0 | }else if(property->value.varint < 16384){ |
97 | 0 | return 3; |
98 | 0 | }else if(property->value.varint < 2097152){ |
99 | 0 | return 4; |
100 | 0 | }else if(property->value.varint < 268435456){ |
101 | 0 | return 5; |
102 | 0 | }else{ |
103 | 0 | return 0; |
104 | 0 | } |
105 | | |
106 | 0 | case MQTT_PROP_TYPE_BINARY: |
107 | 0 | return 3U + property->value.bin.len; /* 1 + 2 bytes (len) + X bytes (payload) */ |
108 | | |
109 | 0 | case MQTT_PROP_TYPE_STRING: |
110 | 0 | return 3U + property->value.s.len; /* 1 + 2 bytes (len) + X bytes (string) */ |
111 | | |
112 | 0 | case MQTT_PROP_TYPE_STRING_PAIR: |
113 | 0 | return 5U + property->value.s.len + property->name.len; /* 1 + 2*(2 bytes (len) + X bytes (string))*/ |
114 | | |
115 | 0 | default: |
116 | 0 | return 0; |
117 | 1.98k | } |
118 | 0 | return 0; |
119 | 1.98k | } |
120 | | |
121 | | |
122 | | unsigned int mosquitto_property_get_length_all(const mosquitto_property *property) |
123 | 2.34k | { |
124 | 2.34k | const mosquitto_property *p; |
125 | 2.34k | unsigned int len = 0; |
126 | | |
127 | 2.34k | p = property; |
128 | 4.33k | while(p){ |
129 | 1.98k | len += mosquitto_property_get_length(p); |
130 | 1.98k | p = p->next; |
131 | 1.98k | } |
132 | 2.34k | return len; |
133 | 2.34k | } |
134 | | |
135 | | |
136 | | BROKER_EXPORT int mosquitto_property_check_command(int command, int identifier) |
137 | 20.0k | { |
138 | 20.0k | switch(identifier){ |
139 | 1.80k | case MQTT_PROP_PAYLOAD_FORMAT_INDICATOR: |
140 | 2.65k | case MQTT_PROP_MESSAGE_EXPIRY_INTERVAL: |
141 | 4.24k | case MQTT_PROP_CONTENT_TYPE: |
142 | 5.81k | case MQTT_PROP_RESPONSE_TOPIC: |
143 | 7.27k | case MQTT_PROP_CORRELATION_DATA: |
144 | 7.27k | if(command != CMD_PUBLISH && command != CMD_WILL){ |
145 | 236 | return MOSQ_ERR_PROTOCOL; |
146 | 236 | } |
147 | 7.03k | break; |
148 | | |
149 | 7.03k | case MQTT_PROP_SUBSCRIPTION_IDENTIFIER: |
150 | 1.74k | if(command != CMD_PUBLISH && command != CMD_SUBSCRIBE){ |
151 | 25 | return MOSQ_ERR_PROTOCOL; |
152 | 25 | } |
153 | 1.71k | break; |
154 | | |
155 | 1.71k | case MQTT_PROP_SESSION_EXPIRY_INTERVAL: |
156 | 91 | if(command != CMD_CONNECT && command != CMD_CONNACK && command != CMD_DISCONNECT){ |
157 | 17 | return MOSQ_ERR_PROTOCOL; |
158 | 17 | } |
159 | 74 | break; |
160 | | |
161 | 169 | case MQTT_PROP_AUTHENTICATION_METHOD: |
162 | 272 | case MQTT_PROP_AUTHENTICATION_DATA: |
163 | 272 | if(command != CMD_CONNECT && command != CMD_CONNACK && command != CMD_AUTH){ |
164 | 49 | return MOSQ_ERR_PROTOCOL; |
165 | 49 | } |
166 | 223 | break; |
167 | | |
168 | 223 | case MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER: |
169 | 72 | case MQTT_PROP_SERVER_KEEP_ALIVE: |
170 | 111 | case MQTT_PROP_RESPONSE_INFORMATION: |
171 | 154 | case MQTT_PROP_MAXIMUM_QOS: |
172 | 198 | case MQTT_PROP_RETAIN_AVAILABLE: |
173 | 245 | case MQTT_PROP_WILDCARD_SUB_AVAILABLE: |
174 | 285 | case MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE: |
175 | 328 | case MQTT_PROP_SHARED_SUB_AVAILABLE: |
176 | 328 | if(command != CMD_CONNACK){ |
177 | 168 | return MOSQ_ERR_PROTOCOL; |
178 | 168 | } |
179 | 160 | break; |
180 | | |
181 | 160 | case MQTT_PROP_WILL_DELAY_INTERVAL: |
182 | 27 | if(command != CMD_WILL){ |
183 | 14 | return MOSQ_ERR_PROTOCOL; |
184 | 14 | } |
185 | 13 | break; |
186 | | |
187 | 70 | case MQTT_PROP_REQUEST_PROBLEM_INFORMATION: |
188 | 143 | case MQTT_PROP_REQUEST_RESPONSE_INFORMATION: |
189 | 143 | if(command != CMD_CONNECT){ |
190 | 34 | return MOSQ_ERR_PROTOCOL; |
191 | 34 | } |
192 | 109 | break; |
193 | | |
194 | 109 | case MQTT_PROP_SERVER_REFERENCE: |
195 | 61 | if(command != CMD_CONNACK && command != CMD_DISCONNECT){ |
196 | 33 | return MOSQ_ERR_PROTOCOL; |
197 | 33 | } |
198 | 28 | break; |
199 | | |
200 | 127 | case MQTT_PROP_REASON_STRING: |
201 | 127 | if(command == CMD_CONNECT || command == CMD_PUBLISH || command == CMD_SUBSCRIBE || command == CMD_UNSUBSCRIBE){ |
202 | 34 | return MOSQ_ERR_PROTOCOL; |
203 | 34 | } |
204 | 93 | break; |
205 | | |
206 | 167 | case MQTT_PROP_RECEIVE_MAXIMUM: |
207 | 306 | case MQTT_PROP_TOPIC_ALIAS_MAXIMUM: |
208 | 801 | case MQTT_PROP_MAXIMUM_PACKET_SIZE: |
209 | 801 | if(command != CMD_CONNECT && command != CMD_CONNACK){ |
210 | 439 | return MOSQ_ERR_PROTOCOL; |
211 | 439 | } |
212 | 362 | break; |
213 | | |
214 | 1.47k | case MQTT_PROP_TOPIC_ALIAS: |
215 | 1.47k | if(command != CMD_PUBLISH){ |
216 | 41 | return MOSQ_ERR_PROTOCOL; |
217 | 41 | } |
218 | 1.43k | break; |
219 | | |
220 | 7.75k | case MQTT_PROP_USER_PROPERTY: |
221 | 7.75k | break; |
222 | | |
223 | 0 | default: |
224 | 0 | return MOSQ_ERR_PROTOCOL; |
225 | 20.0k | } |
226 | 19.0k | return MOSQ_ERR_SUCCESS; |
227 | 20.0k | } |
228 | | |
229 | | |
230 | | BROKER_EXPORT const char *mosquitto_property_identifier_to_string(int identifier) |
231 | 0 | { |
232 | 0 | switch(identifier){ |
233 | 0 | case MQTT_PROP_PAYLOAD_FORMAT_INDICATOR: |
234 | 0 | return "payload-format-indicator"; |
235 | 0 | case MQTT_PROP_MESSAGE_EXPIRY_INTERVAL: |
236 | 0 | return "message-expiry-interval"; |
237 | 0 | case MQTT_PROP_CONTENT_TYPE: |
238 | 0 | return "content-type"; |
239 | 0 | case MQTT_PROP_RESPONSE_TOPIC: |
240 | 0 | return "response-topic"; |
241 | 0 | case MQTT_PROP_CORRELATION_DATA: |
242 | 0 | return "correlation-data"; |
243 | 0 | case MQTT_PROP_SUBSCRIPTION_IDENTIFIER: |
244 | 0 | return "subscription-identifier"; |
245 | 0 | case MQTT_PROP_SESSION_EXPIRY_INTERVAL: |
246 | 0 | return "session-expiry-interval"; |
247 | 0 | case MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER: |
248 | 0 | return "assigned-client-identifier"; |
249 | 0 | case MQTT_PROP_SERVER_KEEP_ALIVE: |
250 | 0 | return "server-keep-alive"; |
251 | 0 | case MQTT_PROP_AUTHENTICATION_METHOD: |
252 | 0 | return "authentication-method"; |
253 | 0 | case MQTT_PROP_AUTHENTICATION_DATA: |
254 | 0 | return "authentication-data"; |
255 | 0 | case MQTT_PROP_REQUEST_PROBLEM_INFORMATION: |
256 | 0 | return "request-problem-information"; |
257 | 0 | case MQTT_PROP_WILL_DELAY_INTERVAL: |
258 | 0 | return "will-delay-interval"; |
259 | 0 | case MQTT_PROP_REQUEST_RESPONSE_INFORMATION: |
260 | 0 | return "request-response-information"; |
261 | 0 | case MQTT_PROP_RESPONSE_INFORMATION: |
262 | 0 | return "response-information"; |
263 | 0 | case MQTT_PROP_SERVER_REFERENCE: |
264 | 0 | return "server-reference"; |
265 | 0 | case MQTT_PROP_REASON_STRING: |
266 | 0 | return "reason-string"; |
267 | 0 | case MQTT_PROP_RECEIVE_MAXIMUM: |
268 | 0 | return "receive-maximum"; |
269 | 0 | case MQTT_PROP_TOPIC_ALIAS_MAXIMUM: |
270 | 0 | return "topic-alias-maximum"; |
271 | 0 | case MQTT_PROP_TOPIC_ALIAS: |
272 | 0 | return "topic-alias"; |
273 | 0 | case MQTT_PROP_MAXIMUM_QOS: |
274 | 0 | return "maximum-qos"; |
275 | 0 | case MQTT_PROP_RETAIN_AVAILABLE: |
276 | 0 | return "retain-available"; |
277 | 0 | case MQTT_PROP_USER_PROPERTY: |
278 | 0 | return "user-property"; |
279 | 0 | case MQTT_PROP_MAXIMUM_PACKET_SIZE: |
280 | 0 | return "maximum-packet-size"; |
281 | 0 | case MQTT_PROP_WILDCARD_SUB_AVAILABLE: |
282 | 0 | return "wildcard-subscription-available"; |
283 | 0 | case MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE: |
284 | 0 | return "subscription-identifier-available"; |
285 | 0 | case MQTT_PROP_SHARED_SUB_AVAILABLE: |
286 | 0 | return "shared-subscription-available"; |
287 | 0 | default: |
288 | 0 | return NULL; |
289 | 0 | } |
290 | 0 | } |
291 | | |
292 | | |
293 | | BROKER_EXPORT int mosquitto_string_to_property_info(const char *propname, int *identifier, int *type) |
294 | 0 | { |
295 | 0 | if(!propname) return MOSQ_ERR_INVAL; |
296 | | |
297 | 0 | if(!strcasecmp(propname, "payload-format-indicator")){ |
298 | 0 | *identifier = MQTT_PROP_PAYLOAD_FORMAT_INDICATOR; |
299 | 0 | *type = MQTT_PROP_TYPE_BYTE; |
300 | 0 | }else if(!strcasecmp(propname, "message-expiry-interval")){ |
301 | 0 | *identifier = MQTT_PROP_MESSAGE_EXPIRY_INTERVAL; |
302 | 0 | *type = MQTT_PROP_TYPE_INT32; |
303 | 0 | }else if(!strcasecmp(propname, "content-type")){ |
304 | 0 | *identifier = MQTT_PROP_CONTENT_TYPE; |
305 | 0 | *type = MQTT_PROP_TYPE_STRING; |
306 | 0 | }else if(!strcasecmp(propname, "response-topic")){ |
307 | 0 | *identifier = MQTT_PROP_RESPONSE_TOPIC; |
308 | 0 | *type = MQTT_PROP_TYPE_STRING; |
309 | 0 | }else if(!strcasecmp(propname, "correlation-data")){ |
310 | 0 | *identifier = MQTT_PROP_CORRELATION_DATA; |
311 | 0 | *type = MQTT_PROP_TYPE_BINARY; |
312 | 0 | }else if(!strcasecmp(propname, "subscription-identifier")){ |
313 | 0 | *identifier = MQTT_PROP_SUBSCRIPTION_IDENTIFIER; |
314 | 0 | *type = MQTT_PROP_TYPE_VARINT; |
315 | 0 | }else if(!strcasecmp(propname, "session-expiry-interval")){ |
316 | 0 | *identifier = MQTT_PROP_SESSION_EXPIRY_INTERVAL; |
317 | 0 | *type = MQTT_PROP_TYPE_INT32; |
318 | 0 | }else if(!strcasecmp(propname, "assigned-client-identifier")){ |
319 | 0 | *identifier = MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER; |
320 | 0 | *type = MQTT_PROP_TYPE_STRING; |
321 | 0 | }else if(!strcasecmp(propname, "server-keep-alive")){ |
322 | 0 | *identifier = MQTT_PROP_SERVER_KEEP_ALIVE; |
323 | 0 | *type = MQTT_PROP_TYPE_INT16; |
324 | 0 | }else if(!strcasecmp(propname, "authentication-method")){ |
325 | 0 | *identifier = MQTT_PROP_AUTHENTICATION_METHOD; |
326 | 0 | *type = MQTT_PROP_TYPE_STRING; |
327 | 0 | }else if(!strcasecmp(propname, "authentication-data")){ |
328 | 0 | *identifier = MQTT_PROP_AUTHENTICATION_DATA; |
329 | 0 | *type = MQTT_PROP_TYPE_BINARY; |
330 | 0 | }else if(!strcasecmp(propname, "request-problem-information")){ |
331 | 0 | *identifier = MQTT_PROP_REQUEST_PROBLEM_INFORMATION; |
332 | 0 | *type = MQTT_PROP_TYPE_BYTE; |
333 | 0 | }else if(!strcasecmp(propname, "will-delay-interval")){ |
334 | 0 | *identifier = MQTT_PROP_WILL_DELAY_INTERVAL; |
335 | 0 | *type = MQTT_PROP_TYPE_INT32; |
336 | 0 | }else if(!strcasecmp(propname, "request-response-information")){ |
337 | 0 | *identifier = MQTT_PROP_REQUEST_RESPONSE_INFORMATION; |
338 | 0 | *type = MQTT_PROP_TYPE_BYTE; |
339 | 0 | }else if(!strcasecmp(propname, "response-information")){ |
340 | 0 | *identifier = MQTT_PROP_RESPONSE_INFORMATION; |
341 | 0 | *type = MQTT_PROP_TYPE_STRING; |
342 | 0 | }else if(!strcasecmp(propname, "server-reference")){ |
343 | 0 | *identifier = MQTT_PROP_SERVER_REFERENCE; |
344 | 0 | *type = MQTT_PROP_TYPE_STRING; |
345 | 0 | }else if(!strcasecmp(propname, "reason-string")){ |
346 | 0 | *identifier = MQTT_PROP_REASON_STRING; |
347 | 0 | *type = MQTT_PROP_TYPE_STRING; |
348 | 0 | }else if(!strcasecmp(propname, "receive-maximum")){ |
349 | 0 | *identifier = MQTT_PROP_RECEIVE_MAXIMUM; |
350 | 0 | *type = MQTT_PROP_TYPE_INT16; |
351 | 0 | }else if(!strcasecmp(propname, "topic-alias-maximum")){ |
352 | 0 | *identifier = MQTT_PROP_TOPIC_ALIAS_MAXIMUM; |
353 | 0 | *type = MQTT_PROP_TYPE_INT16; |
354 | 0 | }else if(!strcasecmp(propname, "topic-alias")){ |
355 | 0 | *identifier = MQTT_PROP_TOPIC_ALIAS; |
356 | 0 | *type = MQTT_PROP_TYPE_INT16; |
357 | 0 | }else if(!strcasecmp(propname, "maximum-qos")){ |
358 | 0 | *identifier = MQTT_PROP_MAXIMUM_QOS; |
359 | 0 | *type = MQTT_PROP_TYPE_BYTE; |
360 | 0 | }else if(!strcasecmp(propname, "retain-available")){ |
361 | 0 | *identifier = MQTT_PROP_RETAIN_AVAILABLE; |
362 | 0 | *type = MQTT_PROP_TYPE_BYTE; |
363 | 0 | }else if(!strcasecmp(propname, "user-property")){ |
364 | 0 | *identifier = MQTT_PROP_USER_PROPERTY; |
365 | 0 | *type = MQTT_PROP_TYPE_STRING_PAIR; |
366 | 0 | }else if(!strcasecmp(propname, "maximum-packet-size")){ |
367 | 0 | *identifier = MQTT_PROP_MAXIMUM_PACKET_SIZE; |
368 | 0 | *type = MQTT_PROP_TYPE_INT32; |
369 | 0 | }else if(!strcasecmp(propname, "wildcard-subscription-available")){ |
370 | 0 | *identifier = MQTT_PROP_WILDCARD_SUB_AVAILABLE; |
371 | 0 | *type = MQTT_PROP_TYPE_BYTE; |
372 | 0 | }else if(!strcasecmp(propname, "subscription-identifier-available")){ |
373 | 0 | *identifier = MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE; |
374 | 0 | *type = MQTT_PROP_TYPE_BYTE; |
375 | 0 | }else if(!strcasecmp(propname, "shared-subscription-available")){ |
376 | 0 | *identifier = MQTT_PROP_SHARED_SUB_AVAILABLE; |
377 | 0 | *type = MQTT_PROP_TYPE_BYTE; |
378 | 0 | }else{ |
379 | 0 | return MOSQ_ERR_INVAL; |
380 | 0 | } |
381 | 0 | return MOSQ_ERR_SUCCESS; |
382 | 0 | } |
383 | | |
384 | | |
385 | | static void property__add(mosquitto_property **proplist, struct mqtt5__property *prop) |
386 | 993 | { |
387 | 993 | mosquitto_property *p; |
388 | | |
389 | 993 | if(!(*proplist)){ |
390 | 990 | *proplist = prop; |
391 | 990 | } |
392 | | |
393 | 993 | p = *proplist; |
394 | 993 | while(p->next){ |
395 | 0 | p = p->next; |
396 | 0 | } |
397 | 993 | p->next = prop; |
398 | 993 | prop->next = NULL; |
399 | 993 | } |
400 | | |
401 | | |
402 | | BROKER_EXPORT int mosquitto_property_add_byte(mosquitto_property **proplist, int identifier, uint8_t value) |
403 | 993 | { |
404 | 993 | mosquitto_property *prop; |
405 | | |
406 | 993 | if(!proplist) return MOSQ_ERR_INVAL; |
407 | 993 | if(identifier != MQTT_PROP_PAYLOAD_FORMAT_INDICATOR |
408 | 993 | && identifier != MQTT_PROP_REQUEST_PROBLEM_INFORMATION |
409 | 993 | && identifier != MQTT_PROP_REQUEST_RESPONSE_INFORMATION |
410 | 993 | && identifier != MQTT_PROP_MAXIMUM_QOS |
411 | 993 | && identifier != MQTT_PROP_RETAIN_AVAILABLE |
412 | 993 | && identifier != MQTT_PROP_WILDCARD_SUB_AVAILABLE |
413 | 993 | && identifier != MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE |
414 | 993 | && identifier != MQTT_PROP_SHARED_SUB_AVAILABLE){ |
415 | 0 | return MOSQ_ERR_INVAL; |
416 | 0 | } |
417 | | |
418 | 993 | prop = mosquitto_calloc(1, sizeof(mosquitto_property)); |
419 | 993 | if(!prop) return MOSQ_ERR_NOMEM; |
420 | | |
421 | 993 | prop->client_generated = true; |
422 | 993 | prop->identifier = identifier; |
423 | 993 | prop->value.i8 = value; |
424 | 993 | prop->property_type = MQTT_PROP_TYPE_BYTE; |
425 | | |
426 | 993 | property__add(proplist, prop); |
427 | 993 | return MOSQ_ERR_SUCCESS; |
428 | 993 | } |
429 | | |
430 | | |
431 | | BROKER_EXPORT int mosquitto_property_add_int16(mosquitto_property **proplist, int identifier, uint16_t value) |
432 | 0 | { |
433 | 0 | mosquitto_property *prop; |
434 | |
|
435 | 0 | if(!proplist) return MOSQ_ERR_INVAL; |
436 | 0 | if(identifier != MQTT_PROP_SERVER_KEEP_ALIVE |
437 | 0 | && identifier != MQTT_PROP_RECEIVE_MAXIMUM |
438 | 0 | && identifier != MQTT_PROP_TOPIC_ALIAS_MAXIMUM |
439 | 0 | && identifier != MQTT_PROP_TOPIC_ALIAS){ |
440 | 0 | return MOSQ_ERR_INVAL; |
441 | 0 | } |
442 | | |
443 | 0 | prop = mosquitto_calloc(1, sizeof(mosquitto_property)); |
444 | 0 | if(!prop) return MOSQ_ERR_NOMEM; |
445 | | |
446 | 0 | prop->client_generated = true; |
447 | 0 | prop->identifier = identifier; |
448 | 0 | prop->value.i16 = value; |
449 | 0 | prop->property_type = MQTT_PROP_TYPE_INT16; |
450 | |
|
451 | 0 | property__add(proplist, prop); |
452 | 0 | return MOSQ_ERR_SUCCESS; |
453 | 0 | } |
454 | | |
455 | | |
456 | | BROKER_EXPORT int mosquitto_property_add_int32(mosquitto_property **proplist, int identifier, uint32_t value) |
457 | 0 | { |
458 | 0 | mosquitto_property *prop; |
459 | |
|
460 | 0 | if(!proplist) return MOSQ_ERR_INVAL; |
461 | 0 | if(identifier != MQTT_PROP_MESSAGE_EXPIRY_INTERVAL |
462 | 0 | && identifier != MQTT_PROP_SESSION_EXPIRY_INTERVAL |
463 | 0 | && identifier != MQTT_PROP_WILL_DELAY_INTERVAL |
464 | 0 | && identifier != MQTT_PROP_MAXIMUM_PACKET_SIZE){ |
465 | |
|
466 | 0 | return MOSQ_ERR_INVAL; |
467 | 0 | } |
468 | | |
469 | 0 | prop = mosquitto_calloc(1, sizeof(mosquitto_property)); |
470 | 0 | if(!prop) return MOSQ_ERR_NOMEM; |
471 | | |
472 | 0 | prop->client_generated = true; |
473 | 0 | prop->identifier = identifier; |
474 | 0 | prop->value.i32 = value; |
475 | 0 | prop->property_type = MQTT_PROP_TYPE_INT32; |
476 | |
|
477 | 0 | property__add(proplist, prop); |
478 | 0 | return MOSQ_ERR_SUCCESS; |
479 | 0 | } |
480 | | |
481 | | |
482 | | BROKER_EXPORT int mosquitto_property_add_varint(mosquitto_property **proplist, int identifier, uint32_t value) |
483 | 0 | { |
484 | 0 | mosquitto_property *prop; |
485 | |
|
486 | 0 | if(!proplist || value > 268435455) return MOSQ_ERR_INVAL; |
487 | 0 | if(identifier != MQTT_PROP_SUBSCRIPTION_IDENTIFIER) return MOSQ_ERR_INVAL; |
488 | | |
489 | 0 | prop = mosquitto_calloc(1, sizeof(mosquitto_property)); |
490 | 0 | if(!prop) return MOSQ_ERR_NOMEM; |
491 | | |
492 | 0 | prop->client_generated = true; |
493 | 0 | prop->identifier = identifier; |
494 | 0 | prop->value.varint = value; |
495 | 0 | prop->property_type = MQTT_PROP_TYPE_VARINT; |
496 | |
|
497 | 0 | property__add(proplist, prop); |
498 | 0 | return MOSQ_ERR_SUCCESS; |
499 | 0 | } |
500 | | |
501 | | |
502 | | BROKER_EXPORT int mosquitto_property_add_binary(mosquitto_property **proplist, int identifier, const void *value, uint16_t len) |
503 | 0 | { |
504 | 0 | mosquitto_property *prop; |
505 | |
|
506 | 0 | if(!proplist) return MOSQ_ERR_INVAL; |
507 | 0 | if(identifier != MQTT_PROP_CORRELATION_DATA |
508 | 0 | && identifier != MQTT_PROP_AUTHENTICATION_DATA){ |
509 | |
|
510 | 0 | return MOSQ_ERR_INVAL; |
511 | 0 | } |
512 | | |
513 | 0 | prop = mosquitto_calloc(1, sizeof(mosquitto_property)); |
514 | 0 | if(!prop) return MOSQ_ERR_NOMEM; |
515 | | |
516 | 0 | prop->client_generated = true; |
517 | 0 | prop->identifier = identifier; |
518 | 0 | prop->property_type = MQTT_PROP_TYPE_BINARY; |
519 | |
|
520 | 0 | if(len){ |
521 | 0 | prop->value.bin.v = mosquitto_malloc(len); |
522 | 0 | if(!prop->value.bin.v){ |
523 | 0 | mosquitto_FREE(prop); |
524 | 0 | return MOSQ_ERR_NOMEM; |
525 | 0 | } |
526 | | |
527 | 0 | memcpy(prop->value.bin.v, value, len); |
528 | 0 | prop->value.bin.len = len; |
529 | 0 | } |
530 | | |
531 | 0 | property__add(proplist, prop); |
532 | 0 | return MOSQ_ERR_SUCCESS; |
533 | 0 | } |
534 | | |
535 | | |
536 | | BROKER_EXPORT int mosquitto_property_add_string(mosquitto_property **proplist, int identifier, const char *value) |
537 | 0 | { |
538 | 0 | mosquitto_property *prop; |
539 | 0 | size_t slen = 0; |
540 | |
|
541 | 0 | if(!proplist) return MOSQ_ERR_INVAL; |
542 | 0 | if(value){ |
543 | 0 | slen = strlen(value); |
544 | 0 | if(mosquitto_validate_utf8(value, (int)slen)) return MOSQ_ERR_MALFORMED_UTF8; |
545 | 0 | } |
546 | | |
547 | 0 | if(identifier != MQTT_PROP_CONTENT_TYPE |
548 | 0 | && identifier != MQTT_PROP_RESPONSE_TOPIC |
549 | 0 | && identifier != MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER |
550 | 0 | && identifier != MQTT_PROP_AUTHENTICATION_METHOD |
551 | 0 | && identifier != MQTT_PROP_RESPONSE_INFORMATION |
552 | 0 | && identifier != MQTT_PROP_SERVER_REFERENCE |
553 | 0 | && identifier != MQTT_PROP_REASON_STRING){ |
554 | |
|
555 | 0 | return MOSQ_ERR_INVAL; |
556 | 0 | } |
557 | | |
558 | 0 | prop = mosquitto_calloc(1, sizeof(mosquitto_property)); |
559 | 0 | if(!prop) return MOSQ_ERR_NOMEM; |
560 | | |
561 | 0 | prop->client_generated = true; |
562 | 0 | prop->identifier = identifier; |
563 | 0 | prop->property_type = MQTT_PROP_TYPE_STRING; |
564 | 0 | if(value && slen > 0){ |
565 | 0 | prop->value.s.v = mosquitto_strdup(value); |
566 | 0 | if(!prop->value.s.v){ |
567 | 0 | mosquitto_FREE(prop); |
568 | 0 | return MOSQ_ERR_NOMEM; |
569 | 0 | } |
570 | 0 | prop->value.s.len = (uint16_t)slen; |
571 | 0 | } |
572 | | |
573 | 0 | property__add(proplist, prop); |
574 | 0 | return MOSQ_ERR_SUCCESS; |
575 | 0 | } |
576 | | |
577 | | |
578 | | BROKER_EXPORT int mosquitto_property_add_string_pair(mosquitto_property **proplist, int identifier, const char *name, const char *value) |
579 | 0 | { |
580 | 0 | mosquitto_property *prop; |
581 | 0 | size_t slen_name = 0, slen_value = 0; |
582 | |
|
583 | 0 | if(!proplist) return MOSQ_ERR_INVAL; |
584 | 0 | if(identifier != MQTT_PROP_USER_PROPERTY) return MOSQ_ERR_INVAL; |
585 | 0 | if(name){ |
586 | 0 | slen_name = strlen(name); |
587 | 0 | if(mosquitto_validate_utf8(name, (int)slen_name)) return MOSQ_ERR_MALFORMED_UTF8; |
588 | 0 | } |
589 | 0 | if(value){ |
590 | 0 | if(mosquitto_validate_utf8(value, (int)slen_value)) return MOSQ_ERR_MALFORMED_UTF8; |
591 | 0 | } |
592 | | |
593 | 0 | prop = mosquitto_calloc(1, sizeof(mosquitto_property)); |
594 | 0 | if(!prop) return MOSQ_ERR_NOMEM; |
595 | | |
596 | 0 | prop->client_generated = true; |
597 | 0 | prop->identifier = identifier; |
598 | 0 | prop->property_type = MQTT_PROP_TYPE_STRING_PAIR; |
599 | |
|
600 | 0 | if(name){ |
601 | 0 | prop->name.v = mosquitto_strdup(name); |
602 | 0 | if(!prop->name.v){ |
603 | 0 | mosquitto_FREE(prop); |
604 | 0 | return MOSQ_ERR_NOMEM; |
605 | 0 | } |
606 | 0 | prop->name.len = (uint16_t)strlen(name); |
607 | 0 | } |
608 | | |
609 | 0 | if(value){ |
610 | 0 | prop->value.s.v = mosquitto_strdup(value); |
611 | 0 | if(!prop->value.s.v){ |
612 | 0 | mosquitto_FREE(prop->name.v); |
613 | 0 | mosquitto_FREE(prop); |
614 | 0 | return MOSQ_ERR_NOMEM; |
615 | 0 | } |
616 | 0 | prop->value.s.len = (uint16_t)strlen(value); |
617 | 0 | } |
618 | | |
619 | 0 | property__add(proplist, prop); |
620 | 0 | return MOSQ_ERR_SUCCESS; |
621 | 0 | } |
622 | | |
623 | | BROKER_EXPORT int mosquitto_property_check_all(int command, const mosquitto_property *properties) |
624 | 10.4k | { |
625 | 10.4k | const mosquitto_property *p, *tail; |
626 | 10.4k | int rc; |
627 | | |
628 | 10.4k | p = properties; |
629 | | |
630 | 29.3k | while(p){ |
631 | | /* Validity checks */ |
632 | 20.2k | if(p->identifier == MQTT_PROP_REQUEST_PROBLEM_INFORMATION |
633 | 20.2k | || p->identifier == MQTT_PROP_PAYLOAD_FORMAT_INDICATOR |
634 | 20.2k | || p->identifier == MQTT_PROP_REQUEST_RESPONSE_INFORMATION |
635 | 20.2k | || p->identifier == MQTT_PROP_MAXIMUM_QOS |
636 | 20.2k | || p->identifier == MQTT_PROP_RETAIN_AVAILABLE |
637 | 20.2k | || p->identifier == MQTT_PROP_WILDCARD_SUB_AVAILABLE |
638 | 20.2k | || p->identifier == MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE |
639 | 20.2k | || p->identifier == MQTT_PROP_SHARED_SUB_AVAILABLE){ |
640 | | |
641 | 2.26k | if(p->value.i8 > 1){ |
642 | 107 | return MOSQ_ERR_PROTOCOL; |
643 | 107 | } |
644 | 17.9k | }else if(p->identifier == MQTT_PROP_MAXIMUM_PACKET_SIZE){ |
645 | 504 | if( p->value.i32 == 0){ |
646 | 9 | return MOSQ_ERR_PROTOCOL; |
647 | 9 | } |
648 | 17.4k | }else if(p->identifier == MQTT_PROP_RECEIVE_MAXIMUM |
649 | 17.4k | || p->identifier == MQTT_PROP_TOPIC_ALIAS){ |
650 | | |
651 | 1.65k | if(p->value.i16 == 0){ |
652 | 10 | return MOSQ_ERR_PROTOCOL; |
653 | 10 | } |
654 | 15.8k | }else if(p->identifier == MQTT_PROP_RESPONSE_TOPIC){ |
655 | 1.61k | if(mosquitto_pub_topic_check(p->value.s.v) != MOSQ_ERR_SUCCESS){ |
656 | 43 | return MOSQ_ERR_PROTOCOL; |
657 | 43 | } |
658 | 1.61k | } |
659 | | |
660 | | /* Check for properties on incorrect commands */ |
661 | 20.0k | rc = mosquitto_property_check_command(command, p->identifier); |
662 | 20.0k | if(rc) return rc; |
663 | | |
664 | | /* Check for duplicates */ |
665 | 19.0k | if(p->identifier != MQTT_PROP_USER_PROPERTY){ |
666 | 11.2k | tail = p->next; |
667 | 31.5k | while(tail){ |
668 | 20.3k | if(p->identifier == tail->identifier){ |
669 | 25 | return MOSQ_ERR_DUPLICATE_PROPERTY; |
670 | 25 | } |
671 | 20.2k | tail = tail->next; |
672 | 20.2k | } |
673 | 11.2k | } |
674 | | |
675 | 18.9k | p = p->next; |
676 | 18.9k | } |
677 | | |
678 | 9.13k | return MOSQ_ERR_SUCCESS; |
679 | 10.4k | } |
680 | | |
681 | | static const mosquitto_property *property__get_property(const mosquitto_property *proplist, int identifier, bool skip_first) |
682 | 1.12k | { |
683 | 1.12k | const mosquitto_property *p; |
684 | 1.12k | bool is_first = true; |
685 | | |
686 | 1.12k | p = proplist; |
687 | | |
688 | 8.56k | while(p){ |
689 | 7.80k | if(p->identifier == identifier){ |
690 | 362 | if(!is_first || !skip_first){ |
691 | 362 | return p; |
692 | 362 | } |
693 | 0 | is_first = false; |
694 | 0 | } |
695 | 7.43k | p = p->next; |
696 | 7.43k | } |
697 | 759 | return NULL; |
698 | 1.12k | } |
699 | | |
700 | | |
701 | | BROKER_EXPORT int mosquitto_property_identifier(const mosquitto_property *property) |
702 | 16.6k | { |
703 | 16.6k | if(property == NULL) return 0; |
704 | | |
705 | 16.6k | return property->identifier; |
706 | 16.6k | } |
707 | | |
708 | | |
709 | | BROKER_EXPORT int mosquitto_property_type(const mosquitto_property *property) |
710 | 0 | { |
711 | 0 | if(property == NULL) return 0; |
712 | | |
713 | 0 | return property->property_type; |
714 | 0 | } |
715 | | |
716 | | |
717 | | BROKER_EXPORT mosquitto_property *mosquitto_property_next(const mosquitto_property *proplist) |
718 | 16.4k | { |
719 | 16.4k | if(proplist == NULL) return NULL; |
720 | | |
721 | 16.4k | return proplist->next; |
722 | 16.4k | } |
723 | | |
724 | | |
725 | | BROKER_EXPORT const mosquitto_property *mosquitto_property_read_byte(const mosquitto_property *proplist, int identifier, uint8_t *value, bool skip_first) |
726 | 266 | { |
727 | 266 | const mosquitto_property *p; |
728 | 266 | if(!proplist) return NULL; |
729 | | |
730 | 180 | p = property__get_property(proplist, identifier, skip_first); |
731 | 180 | if(!p) return NULL; |
732 | 30 | if(p->identifier != MQTT_PROP_PAYLOAD_FORMAT_INDICATOR |
733 | 30 | && p->identifier != MQTT_PROP_REQUEST_PROBLEM_INFORMATION |
734 | 30 | && p->identifier != MQTT_PROP_REQUEST_RESPONSE_INFORMATION |
735 | 30 | && p->identifier != MQTT_PROP_MAXIMUM_QOS |
736 | 30 | && p->identifier != MQTT_PROP_RETAIN_AVAILABLE |
737 | 30 | && p->identifier != MQTT_PROP_WILDCARD_SUB_AVAILABLE |
738 | 30 | && p->identifier != MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE |
739 | 30 | && p->identifier != MQTT_PROP_SHARED_SUB_AVAILABLE){ |
740 | 0 | return NULL; |
741 | 0 | } |
742 | | |
743 | 30 | if(value) *value = p->value.i8; |
744 | | |
745 | 30 | return p; |
746 | 30 | } |
747 | | |
748 | | |
749 | | BROKER_EXPORT const mosquitto_property *mosquitto_property_read_int16(const mosquitto_property *proplist, int identifier, uint16_t *value, bool skip_first) |
750 | 399 | { |
751 | 399 | const mosquitto_property *p; |
752 | 399 | if(!proplist) return NULL; |
753 | | |
754 | 270 | p = property__get_property(proplist, identifier, skip_first); |
755 | 270 | if(!p) return NULL; |
756 | 89 | if(p->identifier != MQTT_PROP_SERVER_KEEP_ALIVE |
757 | 89 | && p->identifier != MQTT_PROP_RECEIVE_MAXIMUM |
758 | 89 | && p->identifier != MQTT_PROP_TOPIC_ALIAS_MAXIMUM |
759 | 89 | && p->identifier != MQTT_PROP_TOPIC_ALIAS){ |
760 | 0 | return NULL; |
761 | 0 | } |
762 | | |
763 | 89 | if(value) *value = p->value.i16; |
764 | | |
765 | 89 | return p; |
766 | 89 | } |
767 | | |
768 | | |
769 | | BROKER_EXPORT const mosquitto_property *mosquitto_property_read_int32(const mosquitto_property *proplist, int identifier, uint32_t *value, bool skip_first) |
770 | 133 | { |
771 | 133 | const mosquitto_property *p; |
772 | 133 | if(!proplist) return NULL; |
773 | | |
774 | 90 | p = property__get_property(proplist, identifier, skip_first); |
775 | 90 | if(!p) return NULL; |
776 | 8 | if(p->identifier != MQTT_PROP_MESSAGE_EXPIRY_INTERVAL |
777 | 8 | && p->identifier != MQTT_PROP_SESSION_EXPIRY_INTERVAL |
778 | 8 | && p->identifier != MQTT_PROP_WILL_DELAY_INTERVAL |
779 | 8 | && p->identifier != MQTT_PROP_MAXIMUM_PACKET_SIZE){ |
780 | |
|
781 | 0 | return NULL; |
782 | 0 | } |
783 | | |
784 | 8 | if(value) *value = p->value.i32; |
785 | | |
786 | 8 | return p; |
787 | 8 | } |
788 | | |
789 | | |
790 | | BROKER_EXPORT const mosquitto_property *mosquitto_property_read_varint(const mosquitto_property *proplist, int identifier, uint32_t *value, bool skip_first) |
791 | 202 | { |
792 | 202 | const mosquitto_property *p; |
793 | 202 | if(!proplist) return NULL; |
794 | | |
795 | 98 | p = property__get_property(proplist, identifier, skip_first); |
796 | 98 | if(!p) return NULL; |
797 | 73 | if(p->identifier != MQTT_PROP_SUBSCRIPTION_IDENTIFIER){ |
798 | 0 | return NULL; |
799 | 0 | } |
800 | | |
801 | 73 | if(value) *value = p->value.varint; |
802 | | |
803 | 73 | return p; |
804 | 73 | } |
805 | | |
806 | | |
807 | | BROKER_EXPORT const mosquitto_property *mosquitto_property_read_binary(const mosquitto_property *proplist, int identifier, void **value, uint16_t *len, bool skip_first) |
808 | 1.00k | { |
809 | 1.00k | const mosquitto_property *p; |
810 | 1.00k | if(!proplist || (value && !len) || (!value && len)) return NULL; |
811 | | |
812 | 208 | if(value) *value = NULL; |
813 | | |
814 | 208 | p = property__get_property(proplist, identifier, skip_first); |
815 | 208 | if(!p) return NULL; |
816 | 47 | if(p->identifier != MQTT_PROP_CORRELATION_DATA |
817 | 47 | && p->identifier != MQTT_PROP_AUTHENTICATION_DATA){ |
818 | |
|
819 | 0 | return NULL; |
820 | 0 | } |
821 | | |
822 | 47 | if(value){ |
823 | 47 | *len = p->value.bin.len; |
824 | 47 | if(p->value.bin.len){ |
825 | 21 | *value = mosquitto_calloc(1, *len + 1U); |
826 | 21 | if(!(*value)) return NULL; |
827 | | |
828 | 21 | memcpy(*value, p->value.bin.v, *len); |
829 | 26 | }else{ |
830 | 26 | *value = NULL; |
831 | 26 | } |
832 | 47 | } |
833 | | |
834 | 47 | return p; |
835 | 47 | } |
836 | | |
837 | | |
838 | | BROKER_EXPORT const mosquitto_property *mosquitto_property_read_string(const mosquitto_property *proplist, int identifier, char **value, bool skip_first) |
839 | 1.07k | { |
840 | 1.07k | const mosquitto_property *p; |
841 | 1.07k | if(!proplist) return NULL; |
842 | | |
843 | 275 | p = property__get_property(proplist, identifier, skip_first); |
844 | 275 | if(!p) return NULL; |
845 | 115 | if(p->identifier != MQTT_PROP_CONTENT_TYPE |
846 | 115 | && p->identifier != MQTT_PROP_RESPONSE_TOPIC |
847 | 115 | && p->identifier != MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER |
848 | 115 | && p->identifier != MQTT_PROP_AUTHENTICATION_METHOD |
849 | 115 | && p->identifier != MQTT_PROP_RESPONSE_INFORMATION |
850 | 115 | && p->identifier != MQTT_PROP_SERVER_REFERENCE |
851 | 115 | && p->identifier != MQTT_PROP_REASON_STRING){ |
852 | |
|
853 | 0 | return NULL; |
854 | 0 | } |
855 | | |
856 | 115 | if(value){ |
857 | 115 | if(p->value.s.len){ |
858 | 79 | *value = mosquitto_calloc(1, (size_t)p->value.s.len+1); |
859 | 79 | if(!(*value)) return NULL; |
860 | | |
861 | 79 | memcpy(*value, p->value.s.v, p->value.s.len); |
862 | 79 | }else{ |
863 | 36 | *value = NULL; |
864 | 36 | } |
865 | 115 | } |
866 | | |
867 | 115 | return p; |
868 | 115 | } |
869 | | |
870 | | |
871 | | BROKER_EXPORT const mosquitto_property *mosquitto_property_read_string_pair(const mosquitto_property *proplist, int identifier, char **name, char **value, bool skip_first) |
872 | 0 | { |
873 | 0 | const mosquitto_property *p; |
874 | 0 | if(!proplist) return NULL; |
875 | | |
876 | 0 | if(name) *name = NULL; |
877 | 0 | if(value) *value = NULL; |
878 | |
|
879 | 0 | p = property__get_property(proplist, identifier, skip_first); |
880 | 0 | if(!p) return NULL; |
881 | 0 | if(p->identifier != MQTT_PROP_USER_PROPERTY) return NULL; |
882 | | |
883 | 0 | if(name){ |
884 | 0 | if(p->name.len){ |
885 | 0 | *name = mosquitto_calloc(1, (size_t)p->name.len+1); |
886 | 0 | if(!(*name)) return NULL; |
887 | 0 | memcpy(*name, p->name.v, p->name.len); |
888 | 0 | }else{ |
889 | 0 | *name = NULL; |
890 | 0 | } |
891 | 0 | } |
892 | | |
893 | 0 | if(value){ |
894 | 0 | if(p->value.s.len){ |
895 | 0 | *value = mosquitto_calloc(1, (size_t)p->value.s.len+1); |
896 | 0 | if(!(*value)){ |
897 | 0 | if(name){ |
898 | 0 | mosquitto_FREE(*name); |
899 | 0 | } |
900 | 0 | return NULL; |
901 | 0 | } |
902 | 0 | memcpy(*value, p->value.s.v, p->value.s.len); |
903 | 0 | }else{ |
904 | 0 | *value = NULL; |
905 | 0 | } |
906 | 0 | } |
907 | | |
908 | 0 | return p; |
909 | 0 | } |
910 | | |
911 | | |
912 | | BROKER_EXPORT int mosquitto_property_remove(mosquitto_property **proplist, const mosquitto_property *property) |
913 | 0 | { |
914 | 0 | mosquitto_property *item, *item_prev = NULL; |
915 | |
|
916 | 0 | if(proplist == NULL || property == NULL){ |
917 | 0 | return MOSQ_ERR_INVAL; |
918 | 0 | } |
919 | | |
920 | 0 | item = *proplist; |
921 | 0 | while(item){ |
922 | 0 | if(item == property){ |
923 | 0 | if(item_prev == NULL){ |
924 | 0 | *proplist = (*proplist)->next; |
925 | 0 | }else{ |
926 | 0 | item_prev->next = item->next; |
927 | 0 | } |
928 | 0 | item->next = NULL; |
929 | 0 | return MOSQ_ERR_SUCCESS; |
930 | 0 | } |
931 | 0 | item_prev = item; |
932 | 0 | item = item->next; |
933 | 0 | } |
934 | | |
935 | 0 | return MOSQ_ERR_NOT_FOUND; |
936 | 0 | } |
937 | | |
938 | | |
939 | | BROKER_EXPORT int mosquitto_property_copy_all(mosquitto_property **dest, const mosquitto_property *src) |
940 | 1.10k | { |
941 | 1.10k | mosquitto_property *pnew, *plast = NULL; |
942 | | |
943 | 1.10k | if(!src) return MOSQ_ERR_SUCCESS; |
944 | 0 | if(!dest) return MOSQ_ERR_INVAL; |
945 | | |
946 | 0 | *dest = NULL; |
947 | |
|
948 | 0 | while(src){ |
949 | 0 | pnew = mosquitto_calloc(1, sizeof(mosquitto_property)); |
950 | 0 | if(!pnew){ |
951 | 0 | mosquitto_property_free_all(dest); |
952 | 0 | return MOSQ_ERR_NOMEM; |
953 | 0 | } |
954 | 0 | if(plast){ |
955 | 0 | plast->next = pnew; |
956 | 0 | }else{ |
957 | 0 | *dest = pnew; |
958 | 0 | } |
959 | 0 | plast = pnew; |
960 | |
|
961 | 0 | pnew->client_generated = src->client_generated; |
962 | 0 | pnew->identifier = src->identifier; |
963 | 0 | pnew->property_type = src->property_type; |
964 | 0 | switch(pnew->property_type){ |
965 | 0 | case MQTT_PROP_TYPE_BYTE: |
966 | 0 | pnew->value.i8 = src->value.i8; |
967 | 0 | break; |
968 | | |
969 | 0 | case MQTT_PROP_TYPE_INT16: |
970 | 0 | pnew->value.i16 = src->value.i16; |
971 | 0 | break; |
972 | | |
973 | 0 | case MQTT_PROP_TYPE_INT32: |
974 | 0 | pnew->value.i32 = src->value.i32; |
975 | 0 | break; |
976 | | |
977 | 0 | case MQTT_PROP_TYPE_VARINT: |
978 | 0 | pnew->value.varint = src->value.varint; |
979 | 0 | break; |
980 | | |
981 | 0 | case MQTT_PROP_TYPE_STRING: |
982 | 0 | pnew->value.s.len = src->value.s.len; |
983 | 0 | pnew->value.s.v = src->value.s.v ? mosquitto_strdup(src->value.s.v) : (char*)mosquitto_calloc(1,1); |
984 | 0 | if(!pnew->value.s.v){ |
985 | 0 | mosquitto_property_free_all(dest); |
986 | 0 | return MOSQ_ERR_NOMEM; |
987 | 0 | } |
988 | 0 | break; |
989 | | |
990 | 0 | case MQTT_PROP_TYPE_BINARY: |
991 | 0 | pnew->value.bin.len = src->value.bin.len; |
992 | 0 | if(src->value.bin.len){ |
993 | 0 | pnew->value.bin.v = mosquitto_malloc(pnew->value.bin.len); |
994 | 0 | if(!pnew->value.bin.v){ |
995 | 0 | mosquitto_property_free_all(dest); |
996 | 0 | return MOSQ_ERR_NOMEM; |
997 | 0 | } |
998 | 0 | memcpy(pnew->value.bin.v, src->value.bin.v, pnew->value.bin.len); |
999 | 0 | } |
1000 | 0 | break; |
1001 | | |
1002 | 0 | case MQTT_PROP_TYPE_STRING_PAIR: |
1003 | 0 | pnew->value.s.len = src->value.s.len; |
1004 | 0 | pnew->value.s.v = src->value.s.v ? mosquitto_strdup(src->value.s.v) : (char*)mosquitto_calloc(1,1); |
1005 | 0 | if(!pnew->value.s.v){ |
1006 | 0 | mosquitto_property_free_all(dest); |
1007 | 0 | return MOSQ_ERR_NOMEM; |
1008 | 0 | } |
1009 | | |
1010 | 0 | pnew->name.len = src->name.len; |
1011 | 0 | pnew->name.v = src->name.v ? mosquitto_strdup(src->name.v) : (char*)mosquitto_calloc(1,1); |
1012 | 0 | if(!pnew->name.v){ |
1013 | 0 | mosquitto_property_free_all(dest); |
1014 | 0 | return MOSQ_ERR_NOMEM; |
1015 | 0 | } |
1016 | 0 | break; |
1017 | | |
1018 | 0 | default: |
1019 | 0 | mosquitto_property_free_all(dest); |
1020 | 0 | return MOSQ_ERR_INVAL; |
1021 | 0 | } |
1022 | | |
1023 | 0 | src = mosquitto_property_next(src); |
1024 | 0 | } |
1025 | | |
1026 | 0 | return MOSQ_ERR_SUCCESS; |
1027 | 0 | } |
1028 | | |
1029 | | |
1030 | | uint8_t mosquitto_property_byte_value(const mosquitto_property *property) |
1031 | 328 | { |
1032 | 328 | if(property && property->property_type == MQTT_PROP_TYPE_BYTE){ |
1033 | 328 | return property->value.i8; |
1034 | 328 | }else{ |
1035 | 0 | return 0; |
1036 | 0 | } |
1037 | 328 | } |
1038 | | |
1039 | | |
1040 | | uint16_t mosquitto_property_int16_value(const mosquitto_property *property) |
1041 | 191 | { |
1042 | 191 | if(property && property->property_type == MQTT_PROP_TYPE_INT16){ |
1043 | 191 | return property->value.i16; |
1044 | 191 | }else{ |
1045 | 0 | return 0; |
1046 | 0 | } |
1047 | 191 | } |
1048 | | |
1049 | | |
1050 | | uint32_t mosquitto_property_int32_value(const mosquitto_property *property) |
1051 | 237 | { |
1052 | 237 | if(property && property->property_type == MQTT_PROP_TYPE_INT32){ |
1053 | 237 | return property->value.i32; |
1054 | 237 | }else{ |
1055 | 0 | return 0; |
1056 | 0 | } |
1057 | 237 | } |
1058 | | |
1059 | | |
1060 | | uint32_t mosquitto_property_varint_value(const mosquitto_property *property) |
1061 | 1.46k | { |
1062 | 1.46k | if(property && property->property_type == MQTT_PROP_TYPE_VARINT){ |
1063 | 1.46k | return property->value.varint; |
1064 | 1.46k | }else{ |
1065 | 0 | return 0; |
1066 | 0 | } |
1067 | 1.46k | } |
1068 | | |
1069 | | |
1070 | | const void *mosquitto_property_binary_value(const mosquitto_property *property) |
1071 | 422 | { |
1072 | 422 | if(property && property->property_type == MQTT_PROP_TYPE_BINARY){ |
1073 | 422 | return property->value.bin.v; |
1074 | 422 | }else{ |
1075 | 0 | return NULL; |
1076 | 0 | } |
1077 | 422 | } |
1078 | | |
1079 | | |
1080 | | uint16_t mosquitto_property_binary_value_length(const mosquitto_property *property) |
1081 | 1.07k | { |
1082 | 1.07k | if(property && property->property_type == MQTT_PROP_TYPE_BINARY){ |
1083 | 1.07k | return property->value.bin.len; |
1084 | 1.07k | }else{ |
1085 | 0 | return 0; |
1086 | 0 | } |
1087 | 1.07k | } |
1088 | | |
1089 | | |
1090 | | const char *mosquitto_property_string_value(const mosquitto_property *property) |
1091 | 679 | { |
1092 | 679 | if(property && (property->property_type == MQTT_PROP_TYPE_STRING || property->property_type == MQTT_PROP_TYPE_STRING_PAIR)){ |
1093 | 679 | return property->value.s.v; |
1094 | 679 | }else{ |
1095 | 0 | return NULL; |
1096 | 0 | } |
1097 | 679 | } |
1098 | | |
1099 | | |
1100 | | uint16_t mosquitto_property_string_value_length(const mosquitto_property *property) |
1101 | 0 | { |
1102 | 0 | if(property && (property->property_type == MQTT_PROP_TYPE_STRING || property->property_type == MQTT_PROP_TYPE_STRING_PAIR)){ |
1103 | 0 | return property->value.s.len; |
1104 | 0 | }else{ |
1105 | 0 | return 0; |
1106 | 0 | } |
1107 | 0 | } |
1108 | | |
1109 | | |
1110 | | const char *mosquitto_property_string_name(const mosquitto_property *property) |
1111 | 195 | { |
1112 | 195 | if(property && property->property_type == MQTT_PROP_TYPE_STRING_PAIR){ |
1113 | 195 | return property->name.v; |
1114 | 195 | }else{ |
1115 | 0 | return NULL; |
1116 | 0 | } |
1117 | 195 | } |
1118 | | |
1119 | | |
1120 | | uint16_t mosquitto_property_string_name_length(const mosquitto_property *property) |
1121 | 0 | { |
1122 | 0 | if(property && property->property_type == MQTT_PROP_TYPE_STRING_PAIR){ |
1123 | 0 | return property->name.len; |
1124 | 0 | }else{ |
1125 | 0 | return 0; |
1126 | 0 | } |
1127 | 0 | } |
1128 | | |
1129 | | /* Return the number of bytes we need to add on to the remaining length when |
1130 | | * encoding these properties. */ |
1131 | | unsigned int mosquitto_property_get_remaining_length(const mosquitto_property *props) |
1132 | 1.17k | { |
1133 | 1.17k | unsigned int proplen, varbytes; |
1134 | | |
1135 | 1.17k | proplen = mosquitto_property_get_length_all(props); |
1136 | 1.17k | varbytes = mosquitto_varint_bytes(proplen); |
1137 | 1.17k | return proplen + varbytes; |
1138 | 1.17k | } |
1139 | | |
1140 | | |