/src/mosquitto/lib/property_mosq.c
Line | Count | Source |
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 <string.h> |
23 | | |
24 | | #ifndef WIN32 |
25 | | # include <strings.h> |
26 | | #endif |
27 | | |
28 | | #include "logging_mosq.h" |
29 | | #include "mosquitto/mqtt_protocol.h" |
30 | | #include "packet_mosq.h" |
31 | | #include "property_common.h" |
32 | | #include "property_mosq.h" |
33 | | |
34 | | |
35 | | static int property__read(struct mosquitto__packet_in *packet, uint32_t *len, mosquitto_property *property) |
36 | 19.3M | { |
37 | 19.3M | int rc; |
38 | 19.3M | uint32_t property_identifier; |
39 | 19.3M | uint8_t byte; |
40 | 19.3M | uint8_t byte_count; |
41 | 19.3M | uint16_t uint16; |
42 | 19.3M | uint32_t uint32; |
43 | 19.3M | uint32_t varint; |
44 | 19.3M | char *str1, *str2; |
45 | 19.3M | uint16_t slen1, slen2; |
46 | | |
47 | 19.3M | if(!property){ |
48 | 0 | return MOSQ_ERR_INVAL; |
49 | 0 | } |
50 | | |
51 | 19.3M | rc = packet__read_varint(packet, &property_identifier, NULL); |
52 | 19.3M | if(rc){ |
53 | 930 | return rc; |
54 | 930 | } |
55 | 19.3M | *len -= mosquitto_varint_bytes(property_identifier); |
56 | | |
57 | 19.3M | memset(property, 0, sizeof(mosquitto_property)); |
58 | | |
59 | 19.3M | property->identifier = (int32_t)property_identifier; |
60 | | |
61 | 19.3M | switch(property_identifier){ |
62 | 4.59M | case MQTT_PROP_PAYLOAD_FORMAT_INDICATOR: |
63 | 8.93M | case MQTT_PROP_REQUEST_PROBLEM_INFORMATION: |
64 | 9.60M | case MQTT_PROP_REQUEST_RESPONSE_INFORMATION: |
65 | 10.4M | case MQTT_PROP_MAXIMUM_QOS: |
66 | 11.9M | case MQTT_PROP_RETAIN_AVAILABLE: |
67 | 13.1M | case MQTT_PROP_WILDCARD_SUB_AVAILABLE: |
68 | 14.0M | case MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE: |
69 | 14.8M | case MQTT_PROP_SHARED_SUB_AVAILABLE: |
70 | 14.8M | rc = packet__read_byte(packet, &byte); |
71 | 14.8M | if(rc){ |
72 | 580 | return rc; |
73 | 580 | } |
74 | 14.8M | *len -= 1; /* byte */ |
75 | 14.8M | property->value.i8 = byte; |
76 | 14.8M | property->property_type = MQTT_PROP_TYPE_BYTE; |
77 | 14.8M | break; |
78 | | |
79 | 419k | case MQTT_PROP_SERVER_KEEP_ALIVE: |
80 | 602k | case MQTT_PROP_RECEIVE_MAXIMUM: |
81 | 870k | case MQTT_PROP_TOPIC_ALIAS_MAXIMUM: |
82 | 965k | case MQTT_PROP_TOPIC_ALIAS: |
83 | 965k | rc = packet__read_uint16(packet, &uint16); |
84 | 965k | if(rc){ |
85 | 315 | return rc; |
86 | 315 | } |
87 | 965k | *len -= 2; /* uint16 */ |
88 | 965k | property->value.i16 = uint16; |
89 | 965k | property->property_type = MQTT_PROP_TYPE_INT16; |
90 | 965k | break; |
91 | | |
92 | 222k | case MQTT_PROP_MESSAGE_EXPIRY_INTERVAL: |
93 | 336k | case MQTT_PROP_SESSION_EXPIRY_INTERVAL: |
94 | 342k | case MQTT_PROP_WILL_DELAY_INTERVAL: |
95 | 503k | case MQTT_PROP_MAXIMUM_PACKET_SIZE: |
96 | 503k | rc = packet__read_uint32(packet, &uint32); |
97 | 503k | if(rc){ |
98 | 309 | return rc; |
99 | 309 | } |
100 | 503k | *len -= 4; /* uint32 */ |
101 | 503k | property->value.i32 = uint32; |
102 | 503k | property->property_type = MQTT_PROP_TYPE_INT32; |
103 | 503k | break; |
104 | | |
105 | 1.25M | case MQTT_PROP_SUBSCRIPTION_IDENTIFIER: |
106 | 1.25M | rc = packet__read_varint(packet, &varint, &byte_count); |
107 | 1.25M | if(rc){ |
108 | 43 | return rc; |
109 | 43 | } |
110 | 1.25M | *len -= byte_count; |
111 | 1.25M | property->value.varint = varint; |
112 | 1.25M | property->property_type = MQTT_PROP_TYPE_VARINT; |
113 | 1.25M | break; |
114 | | |
115 | 163k | case MQTT_PROP_CONTENT_TYPE: |
116 | 314k | case MQTT_PROP_RESPONSE_TOPIC: |
117 | 483k | case MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER: |
118 | 489k | case MQTT_PROP_AUTHENTICATION_METHOD: |
119 | 497k | case MQTT_PROP_RESPONSE_INFORMATION: |
120 | 511k | case MQTT_PROP_SERVER_REFERENCE: |
121 | 562k | case MQTT_PROP_REASON_STRING: |
122 | 562k | rc = packet__read_string(packet, &str1, &slen1); |
123 | 562k | if(rc){ |
124 | 964 | return rc; |
125 | 964 | } |
126 | 561k | *len = (*len) - 2 - slen1; /* uint16, string len */ |
127 | 561k | property->value.s.v = str1; |
128 | 561k | property->value.s.len = slen1; |
129 | 561k | property->property_type = MQTT_PROP_TYPE_STRING; |
130 | 561k | break; |
131 | | |
132 | 747k | case MQTT_PROP_AUTHENTICATION_DATA: |
133 | 1.14M | case MQTT_PROP_CORRELATION_DATA: |
134 | 1.14M | rc = packet__read_binary(packet, (uint8_t **)&str1, &slen1); |
135 | 1.14M | if(rc){ |
136 | 397 | return rc; |
137 | 397 | } |
138 | 1.14M | *len = (*len) - 2 - slen1; /* uint16, binary len */ |
139 | 1.14M | property->value.bin.v = str1; |
140 | 1.14M | property->value.bin.len = slen1; |
141 | 1.14M | property->property_type = MQTT_PROP_TYPE_BINARY; |
142 | 1.14M | break; |
143 | | |
144 | 11.6k | case MQTT_PROP_USER_PROPERTY: |
145 | 11.6k | rc = packet__read_string(packet, &str1, &slen1); |
146 | 11.6k | if(rc){ |
147 | 88 | return rc; |
148 | 88 | } |
149 | 11.5k | *len = (*len) - 2 - slen1; /* uint16, string len */ |
150 | | |
151 | 11.5k | rc = packet__read_string(packet, &str2, &slen2); |
152 | 11.5k | if(rc){ |
153 | 106 | mosquitto_FREE(str1); |
154 | 106 | return rc; |
155 | 106 | } |
156 | 11.4k | *len = (*len) - 2 - slen2; /* uint16, string len */ |
157 | | |
158 | 11.4k | property->name.v = str1; |
159 | 11.4k | property->name.len = slen1; |
160 | 11.4k | property->value.s.v = str2; |
161 | 11.4k | property->value.s.len = slen2; |
162 | 11.4k | property->property_type = MQTT_PROP_TYPE_STRING_PAIR; |
163 | 11.4k | break; |
164 | | |
165 | 1.01k | default: |
166 | 1.01k | #ifdef WITH_BROKER |
167 | 1.01k | log__printf(NULL, MOSQ_LOG_DEBUG, "Unsupported property type: %d", property_identifier); |
168 | 1.01k | #endif |
169 | 1.01k | return MOSQ_ERR_MALFORMED_PACKET; |
170 | 19.3M | } |
171 | | |
172 | 19.3M | return MOSQ_ERR_SUCCESS; |
173 | 19.3M | } |
174 | | |
175 | | |
176 | | int property__read_all(int command, struct mosquitto__packet_in *packet, mosquitto_property **properties) |
177 | 14.3k | { |
178 | 14.3k | int rc; |
179 | 14.3k | uint32_t proplen; |
180 | 14.3k | mosquitto_property *p, *tail = NULL; |
181 | | |
182 | 14.3k | rc = packet__read_varint(packet, &proplen, NULL); |
183 | 14.3k | if(rc){ |
184 | 131 | return rc; |
185 | 131 | } |
186 | | |
187 | 14.1k | *properties = NULL; |
188 | | |
189 | | /* The order of properties must be preserved for some types, so keep the |
190 | | * same order for all */ |
191 | 19.3M | while(proplen > 0){ |
192 | 19.3M | p = mosquitto_calloc(1, sizeof(mosquitto_property)); |
193 | 19.3M | if(!p){ |
194 | 0 | mosquitto_property_free_all(properties); |
195 | 0 | return MOSQ_ERR_NOMEM; |
196 | 0 | } |
197 | | |
198 | 19.3M | rc = property__read(packet, &proplen, p); |
199 | 19.3M | if(rc){ |
200 | 4.74k | mosquitto_FREE(p); |
201 | 4.74k | mosquitto_property_free_all(properties); |
202 | 4.74k | return rc; |
203 | 4.74k | } |
204 | | |
205 | 19.3M | if(!(*properties)){ |
206 | 10.8k | *properties = p; |
207 | 19.3M | }else{ |
208 | 19.3M | tail->next = p; |
209 | 19.3M | } |
210 | 19.3M | tail = p; |
211 | | |
212 | 19.3M | } |
213 | | |
214 | 9.44k | rc = mosquitto_property_check_all(command, *properties); |
215 | 9.44k | if(rc){ |
216 | 956 | mosquitto_property_free_all(properties); |
217 | 956 | return rc; |
218 | 956 | } |
219 | 8.49k | return MOSQ_ERR_SUCCESS; |
220 | 9.44k | } |
221 | | |
222 | | |
223 | | static int property__write(struct mosquitto__packet *packet, const mosquitto_property *property) |
224 | 1.30k | { |
225 | 1.30k | int rc; |
226 | | |
227 | 1.30k | rc = packet__write_varint(packet, (uint32_t)mosquitto_property_identifier(property)); |
228 | 1.30k | if(rc){ |
229 | 0 | return rc; |
230 | 0 | } |
231 | | |
232 | 1.30k | switch(property->property_type){ |
233 | 1.30k | case MQTT_PROP_TYPE_BYTE: |
234 | 1.30k | packet__write_byte(packet, property->value.i8); |
235 | 1.30k | break; |
236 | | |
237 | 0 | case MQTT_PROP_TYPE_INT16: |
238 | 0 | packet__write_uint16(packet, property->value.i16); |
239 | 0 | break; |
240 | | |
241 | 0 | case MQTT_PROP_TYPE_INT32: |
242 | 0 | packet__write_uint32(packet, property->value.i32); |
243 | 0 | break; |
244 | | |
245 | 0 | case MQTT_PROP_TYPE_VARINT: |
246 | 0 | return packet__write_varint(packet, property->value.varint); |
247 | | |
248 | 0 | case MQTT_PROP_TYPE_STRING: |
249 | 0 | packet__write_string(packet, property->value.s.v, property->value.s.len); |
250 | 0 | break; |
251 | | |
252 | 0 | case MQTT_PROP_TYPE_BINARY: |
253 | 0 | packet__write_uint16(packet, property->value.bin.len); |
254 | 0 | packet__write_bytes(packet, property->value.bin.v, property->value.bin.len); |
255 | 0 | break; |
256 | | |
257 | 0 | case MQTT_PROP_TYPE_STRING_PAIR: |
258 | 0 | packet__write_string(packet, property->name.v, property->name.len); |
259 | 0 | packet__write_string(packet, property->value.s.v, property->value.s.len); |
260 | 0 | break; |
261 | | |
262 | 0 | default: |
263 | 0 | #ifdef WITH_BROKER |
264 | 0 | log__printf(NULL, MOSQ_LOG_DEBUG, "Unsupported property type: %d", property->identifier); |
265 | 0 | #endif |
266 | 0 | return MOSQ_ERR_INVAL; |
267 | 1.30k | } |
268 | | |
269 | 1.30k | return MOSQ_ERR_SUCCESS; |
270 | 1.30k | } |
271 | | |
272 | | |
273 | | int property__write_all(struct mosquitto__packet *packet, const mosquitto_property *properties, bool write_len) |
274 | 1.49k | { |
275 | 1.49k | int rc; |
276 | 1.49k | const mosquitto_property *p; |
277 | | |
278 | 1.49k | if(write_len){ |
279 | 1.49k | rc = packet__write_varint(packet, mosquitto_property_get_length_all(properties)); |
280 | 1.49k | if(rc){ |
281 | 0 | return rc; |
282 | 0 | } |
283 | 1.49k | } |
284 | | |
285 | 1.49k | p = properties; |
286 | 2.80k | while(p){ |
287 | 1.30k | rc = property__write(packet, p); |
288 | 1.30k | if(rc){ |
289 | 0 | return rc; |
290 | 0 | } |
291 | 1.30k | p = p->next; |
292 | 1.30k | } |
293 | | |
294 | 1.49k | return MOSQ_ERR_SUCCESS; |
295 | 1.49k | } |