/src/mosquitto/lib/property_mosq.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 <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 | 24.5M | { |
37 | 24.5M | int rc; |
38 | 24.5M | uint32_t property_identifier; |
39 | 24.5M | uint8_t byte; |
40 | 24.5M | uint8_t byte_count; |
41 | 24.5M | uint16_t uint16; |
42 | 24.5M | uint32_t uint32; |
43 | 24.5M | uint32_t varint; |
44 | 24.5M | char *str1, *str2; |
45 | 24.5M | uint16_t slen1, slen2; |
46 | | |
47 | 24.5M | if(!property) return MOSQ_ERR_INVAL; |
48 | | |
49 | 24.5M | rc = packet__read_varint(packet, &property_identifier, NULL); |
50 | 24.5M | if(rc){ |
51 | 1.31k | return rc; |
52 | 1.31k | } |
53 | 24.5M | *len -= 1; |
54 | | |
55 | 24.5M | memset(property, 0, sizeof(mosquitto_property)); |
56 | | |
57 | 24.5M | property->identifier = (int32_t)property_identifier; |
58 | | |
59 | 24.5M | switch(property_identifier){ |
60 | 6.58M | case MQTT_PROP_PAYLOAD_FORMAT_INDICATOR: |
61 | 10.4M | case MQTT_PROP_REQUEST_PROBLEM_INFORMATION: |
62 | 11.1M | case MQTT_PROP_REQUEST_RESPONSE_INFORMATION: |
63 | 12.1M | case MQTT_PROP_MAXIMUM_QOS: |
64 | 13.6M | case MQTT_PROP_RETAIN_AVAILABLE: |
65 | 15.2M | case MQTT_PROP_WILDCARD_SUB_AVAILABLE: |
66 | 17.2M | case MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE: |
67 | 18.3M | case MQTT_PROP_SHARED_SUB_AVAILABLE: |
68 | 18.3M | rc = packet__read_byte(packet, &byte); |
69 | 18.3M | if(rc) return rc; |
70 | 18.3M | *len -= 1; /* byte */ |
71 | 18.3M | property->value.i8 = byte; |
72 | 18.3M | property->property_type = MQTT_PROP_TYPE_BYTE; |
73 | 18.3M | break; |
74 | | |
75 | 693k | case MQTT_PROP_SERVER_KEEP_ALIVE: |
76 | 1.03M | case MQTT_PROP_RECEIVE_MAXIMUM: |
77 | 1.64M | case MQTT_PROP_TOPIC_ALIAS_MAXIMUM: |
78 | 1.78M | case MQTT_PROP_TOPIC_ALIAS: |
79 | 1.78M | rc = packet__read_uint16(packet, &uint16); |
80 | 1.78M | if(rc) return rc; |
81 | 1.77M | *len -= 2; /* uint16 */ |
82 | 1.77M | property->value.i16 = uint16; |
83 | 1.77M | property->property_type = MQTT_PROP_TYPE_INT16; |
84 | 1.77M | break; |
85 | | |
86 | 247k | case MQTT_PROP_MESSAGE_EXPIRY_INTERVAL: |
87 | 404k | case MQTT_PROP_SESSION_EXPIRY_INTERVAL: |
88 | 413k | case MQTT_PROP_WILL_DELAY_INTERVAL: |
89 | 645k | case MQTT_PROP_MAXIMUM_PACKET_SIZE: |
90 | 645k | rc = packet__read_uint32(packet, &uint32); |
91 | 645k | if(rc) return rc; |
92 | 645k | *len -= 4; /* uint32 */ |
93 | 645k | property->value.i32 = uint32; |
94 | 645k | property->property_type = MQTT_PROP_TYPE_INT32; |
95 | 645k | break; |
96 | | |
97 | 1.21M | case MQTT_PROP_SUBSCRIPTION_IDENTIFIER: |
98 | 1.21M | rc = packet__read_varint(packet, &varint, &byte_count); |
99 | 1.21M | if(rc) return rc; |
100 | 1.21M | *len -= byte_count; |
101 | 1.21M | property->value.varint = varint; |
102 | 1.21M | property->property_type = MQTT_PROP_TYPE_VARINT; |
103 | 1.21M | break; |
104 | | |
105 | 279k | case MQTT_PROP_CONTENT_TYPE: |
106 | 366k | case MQTT_PROP_RESPONSE_TOPIC: |
107 | 518k | case MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER: |
108 | 742k | case MQTT_PROP_AUTHENTICATION_METHOD: |
109 | 751k | case MQTT_PROP_RESPONSE_INFORMATION: |
110 | 808k | case MQTT_PROP_SERVER_REFERENCE: |
111 | 867k | case MQTT_PROP_REASON_STRING: |
112 | 867k | rc = packet__read_string(packet, &str1, &slen1); |
113 | 867k | if(rc) return rc; |
114 | 865k | *len = (*len) - 2 - slen1; /* uint16, string len */ |
115 | 865k | property->value.s.v = str1; |
116 | 865k | property->value.s.len = slen1; |
117 | 865k | property->property_type = MQTT_PROP_TYPE_STRING; |
118 | 865k | break; |
119 | | |
120 | 1.20M | case MQTT_PROP_AUTHENTICATION_DATA: |
121 | 1.59M | case MQTT_PROP_CORRELATION_DATA: |
122 | 1.59M | rc = packet__read_binary(packet, (uint8_t **)&str1, &slen1); |
123 | 1.59M | if(rc) return rc; |
124 | 1.59M | *len = (*len) - 2 - slen1; /* uint16, binary len */ |
125 | 1.59M | property->value.bin.v = str1; |
126 | 1.59M | property->value.bin.len = slen1; |
127 | 1.59M | property->property_type = MQTT_PROP_TYPE_BINARY; |
128 | 1.59M | break; |
129 | | |
130 | 14.8k | case MQTT_PROP_USER_PROPERTY: |
131 | 14.8k | rc = packet__read_string(packet, &str1, &slen1); |
132 | 14.8k | if(rc) return rc; |
133 | 14.6k | *len = (*len) - 2 - slen1; /* uint16, string len */ |
134 | | |
135 | 14.6k | rc = packet__read_string(packet, &str2, &slen2); |
136 | 14.6k | if(rc){ |
137 | 133 | mosquitto_FREE(str1); |
138 | 133 | return rc; |
139 | 133 | } |
140 | 14.5k | *len = (*len) - 2 - slen2; /* uint16, string len */ |
141 | | |
142 | 14.5k | property->name.v = str1; |
143 | 14.5k | property->name.len = slen1; |
144 | 14.5k | property->value.s.v = str2; |
145 | 14.5k | property->value.s.len = slen2; |
146 | 14.5k | property->property_type = MQTT_PROP_TYPE_STRING_PAIR; |
147 | 14.5k | break; |
148 | | |
149 | 451 | default: |
150 | 451 | #ifdef WITH_BROKER |
151 | 451 | log__printf(NULL, MOSQ_LOG_DEBUG, "Unsupported property type: %d", property_identifier); |
152 | 451 | #endif |
153 | 451 | return MOSQ_ERR_MALFORMED_PACKET; |
154 | 24.5M | } |
155 | | |
156 | 24.5M | return MOSQ_ERR_SUCCESS; |
157 | 24.5M | } |
158 | | |
159 | | |
160 | | int property__read_all(int command, struct mosquitto__packet_in *packet, mosquitto_property **properties) |
161 | 15.8k | { |
162 | 15.8k | int rc; |
163 | 15.8k | uint32_t proplen; |
164 | 15.8k | mosquitto_property *p, *tail = NULL; |
165 | | |
166 | 15.8k | rc = packet__read_varint(packet, &proplen, NULL); |
167 | 15.8k | if(rc) return rc; |
168 | | |
169 | 15.6k | *properties = NULL; |
170 | | |
171 | | /* The order of properties must be preserved for some types, so keep the |
172 | | * same order for all */ |
173 | 24.5M | while(proplen > 0){ |
174 | 24.5M | p = mosquitto_calloc(1, sizeof(mosquitto_property)); |
175 | 24.5M | if(!p){ |
176 | 0 | mosquitto_property_free_all(properties); |
177 | 0 | return MOSQ_ERR_NOMEM; |
178 | 0 | } |
179 | | |
180 | 24.5M | rc = property__read(packet, &proplen, p); |
181 | 24.5M | if(rc){ |
182 | 5.28k | mosquitto_FREE(p); |
183 | 5.28k | mosquitto_property_free_all(properties); |
184 | 5.28k | return rc; |
185 | 5.28k | } |
186 | | |
187 | 24.5M | if(!(*properties)){ |
188 | 12.3k | *properties = p; |
189 | 24.4M | }else{ |
190 | 24.4M | tail->next = p; |
191 | 24.4M | } |
192 | 24.5M | tail = p; |
193 | | |
194 | 24.5M | } |
195 | | |
196 | 10.3k | rc = mosquitto_property_check_all(command, *properties); |
197 | 10.3k | if(rc){ |
198 | 1.30k | mosquitto_property_free_all(properties); |
199 | 1.30k | return rc; |
200 | 1.30k | } |
201 | 9.05k | return MOSQ_ERR_SUCCESS; |
202 | 10.3k | } |
203 | | |
204 | | |
205 | | static int property__write(struct mosquitto__packet *packet, const mosquitto_property *property) |
206 | 1.03k | { |
207 | 1.03k | int rc; |
208 | | |
209 | 1.03k | rc = packet__write_varint(packet, (uint32_t)mosquitto_property_identifier(property)); |
210 | 1.03k | if(rc) return rc; |
211 | | |
212 | 1.03k | switch(property->property_type){ |
213 | 1.03k | case MQTT_PROP_TYPE_BYTE: |
214 | 1.03k | packet__write_byte(packet, property->value.i8); |
215 | 1.03k | break; |
216 | | |
217 | 0 | case MQTT_PROP_TYPE_INT16: |
218 | 0 | packet__write_uint16(packet, property->value.i16); |
219 | 0 | break; |
220 | | |
221 | 0 | case MQTT_PROP_TYPE_INT32: |
222 | 0 | packet__write_uint32(packet, property->value.i32); |
223 | 0 | break; |
224 | | |
225 | 0 | case MQTT_PROP_TYPE_VARINT: |
226 | 0 | return packet__write_varint(packet, property->value.varint); |
227 | | |
228 | 0 | case MQTT_PROP_TYPE_STRING: |
229 | 0 | packet__write_string(packet, property->value.s.v, property->value.s.len); |
230 | 0 | break; |
231 | | |
232 | 0 | case MQTT_PROP_TYPE_BINARY: |
233 | 0 | packet__write_uint16(packet, property->value.bin.len); |
234 | 0 | packet__write_bytes(packet, property->value.bin.v, property->value.bin.len); |
235 | 0 | break; |
236 | | |
237 | 0 | case MQTT_PROP_TYPE_STRING_PAIR: |
238 | 0 | packet__write_string(packet, property->name.v, property->name.len); |
239 | 0 | packet__write_string(packet, property->value.s.v, property->value.s.len); |
240 | 0 | break; |
241 | | |
242 | 0 | default: |
243 | 0 | #ifdef WITH_BROKER |
244 | 0 | log__printf(NULL, MOSQ_LOG_DEBUG, "Unsupported property type: %d", property->identifier); |
245 | 0 | #endif |
246 | 0 | return MOSQ_ERR_INVAL; |
247 | 1.03k | } |
248 | | |
249 | 1.03k | return MOSQ_ERR_SUCCESS; |
250 | 1.03k | } |
251 | | |
252 | | |
253 | | int property__write_all(struct mosquitto__packet *packet, const mosquitto_property *properties, bool write_len) |
254 | 1.20k | { |
255 | 1.20k | int rc; |
256 | 1.20k | const mosquitto_property *p; |
257 | | |
258 | 1.20k | if(write_len){ |
259 | 1.20k | rc = packet__write_varint(packet, mosquitto_property_get_length_all(properties)); |
260 | 1.20k | if(rc) return rc; |
261 | 1.20k | } |
262 | | |
263 | 1.20k | p = properties; |
264 | 2.24k | while(p){ |
265 | 1.03k | rc = property__write(packet, p); |
266 | 1.03k | if(rc) return rc; |
267 | 1.03k | p = p->next; |
268 | 1.03k | } |
269 | | |
270 | 1.20k | return MOSQ_ERR_SUCCESS; |
271 | 1.20k | } |