1 /* 2 * Copyright (c) 2018 Nordic Semiconductor ASA 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 /** @file mqtt_internal.h 8 * 9 * @brief Function and data structures internal to MQTT module. 10 */ 11 12 #ifndef MQTT_INTERNAL_H_ 13 #define MQTT_INTERNAL_H_ 14 15 #include <stdint.h> 16 #include <string.h> 17 18 #include <zephyr/net/mqtt.h> 19 20 #ifdef __cplusplus 21 extern "C" { 22 #endif 23 24 /**@brief Keep alive time for MQTT (in seconds). Sending of Ping Requests to 25 * keep the connection alive are governed by this value. 26 */ 27 #define MQTT_KEEPALIVE CONFIG_MQTT_KEEPALIVE 28 29 /**@brief Clean session on every connect (1) or keep subscriptions and messages 30 * between connects (0) 31 */ 32 #define MQTT_CLEAN_SESSION (IS_ENABLED(CONFIG_MQTT_CLEAN_SESSION) ? 1U : 0U) 33 34 /**@brief Minimum mandatory size of fixed header. */ 35 #define MQTT_FIXED_HEADER_MIN_SIZE 2 36 37 /**@brief Maximum size of the fixed header. Remaining length size is 4 in this 38 * case. 39 */ 40 #define MQTT_FIXED_HEADER_MAX_SIZE 5 41 42 /**@brief MQTT Control Packet Types. */ 43 #define MQTT_PKT_TYPE_CONNECT 0x10 44 #define MQTT_PKT_TYPE_CONNACK 0x20 45 #define MQTT_PKT_TYPE_PUBLISH 0x30 46 #define MQTT_PKT_TYPE_PUBACK 0x40 47 #define MQTT_PKT_TYPE_PUBREC 0x50 48 #define MQTT_PKT_TYPE_PUBREL 0x60 49 #define MQTT_PKT_TYPE_PUBCOMP 0x70 50 #define MQTT_PKT_TYPE_SUBSCRIBE 0x80 51 #define MQTT_PKT_TYPE_SUBACK 0x90 52 #define MQTT_PKT_TYPE_UNSUBSCRIBE 0xA0 53 #define MQTT_PKT_TYPE_UNSUBACK 0xB0 54 #define MQTT_PKT_TYPE_PINGREQ 0xC0 55 #define MQTT_PKT_TYPE_PINGRSP 0xD0 56 #define MQTT_PKT_TYPE_DISCONNECT 0xE0 57 58 /**@brief Masks for MQTT header flags. */ 59 #define MQTT_HEADER_DUP_MASK 0x08 60 #define MQTT_HEADER_QOS_MASK 0x06 61 #define MQTT_HEADER_RETAIN_MASK 0x01 62 63 /**@brief Masks for MQTT header flags. */ 64 #define MQTT_CONNECT_FLAG_CLEAN_SESSION 0x02 65 #define MQTT_CONNECT_FLAG_WILL_TOPIC 0x04 66 #define MQTT_CONNECT_FLAG_WILL_RETAIN 0x20 67 #define MQTT_CONNECT_FLAG_PASSWORD 0x40 68 #define MQTT_CONNECT_FLAG_USERNAME 0x80 69 70 #define MQTT_CONNACK_FLAG_SESSION_PRESENT 0x01 71 72 /**@brief Maximum payload size of MQTT packet. */ 73 #define MQTT_MAX_PAYLOAD_SIZE 0x0FFFFFFF 74 75 /**@brief Computes total size needed to pack a UTF8 string. */ 76 #define GET_UT8STR_BUFFER_SIZE(STR) (sizeof(uint16_t) + (STR)->size) 77 78 /**@brief Computes total size needed to pack a binary stream. */ 79 #define GET_BINSTR_BUFFER_SIZE(STR) ((STR)->len) 80 81 /**@brief Sets MQTT Client's state with one indicated in 'STATE'. */ 82 #define MQTT_SET_STATE(CLIENT, STATE) ((CLIENT)->internal.state |= (STATE)) 83 84 /**@brief Sets MQTT Client's state exclusive to 'STATE'. */ 85 #define MQTT_SET_STATE_EXCLUSIVE(CLIENT, STATE) \ 86 ((CLIENT)->internal.state = (STATE)) 87 88 /**@brief Verifies if MQTT Client's state is set with one indicated in 'STATE'. 89 */ 90 #define MQTT_HAS_STATE(CLIENT, STATE) ((CLIENT)->internal.state & (STATE)) 91 92 /**@brief Reset 'STATE' in MQTT Client's state. */ 93 #define MQTT_RESET_STATE(CLIENT, STATE) ((CLIENT)->internal.state &= ~(STATE)) 94 95 /**@brief Initialize MQTT Client's state. */ 96 #define MQTT_STATE_INIT(CLIENT) ((CLIENT)->internal.state = MQTT_STATE_IDLE) 97 98 /**@brief Computes the first byte of MQTT message header based on message type, 99 * duplication flag, QoS and the retain flag. 100 */ 101 #define MQTT_MESSAGES_OPTIONS(TYPE, DUP, QOS, RETAIN) \ 102 (((TYPE) & 0xF0) | \ 103 (((DUP) << 3) & 0x08) | \ 104 (((QOS) << 1) & 0x06) | \ 105 ((RETAIN) & 0x01)) 106 107 #define MQTT_MAX_LENGTH_BYTES 4 108 #define MQTT_LENGTH_VALUE_MASK 0x7F 109 #define MQTT_LENGTH_CONTINUATION_BIT 0x80 110 #define MQTT_LENGTH_SHIFT 7 111 112 /**@brief Check if the input pointer is NULL, if so it returns -EINVAL. */ 113 #define NULL_PARAM_CHECK(param) \ 114 do { \ 115 if ((param) == NULL) { \ 116 return -EINVAL; \ 117 } \ 118 } while (false) 119 120 #define NULL_PARAM_CHECK_VOID(param) \ 121 do { \ 122 if ((param) == NULL) { \ 123 return; \ 124 } \ 125 } while (false) 126 127 /** Buffer context to iterate over buffer. */ 128 struct buf_ctx { 129 uint8_t *cur; 130 uint8_t *end; 131 }; 132 133 /**@brief MQTT States. */ 134 enum mqtt_state { 135 /** Idle state, implying the client entry in the table is unused/free. 136 */ 137 MQTT_STATE_IDLE = 0x00000000, 138 139 /** TCP Connection has been requested, awaiting result of the request. 140 */ 141 MQTT_STATE_TCP_CONNECTING = 0x00000001, 142 143 /** TCP Connection successfully established. */ 144 MQTT_STATE_TCP_CONNECTED = 0x00000002, 145 146 /** MQTT Connection successful. */ 147 MQTT_STATE_CONNECTED = 0x00000004, 148 }; 149 150 /**@brief Notify application about MQTT event. 151 * 152 * @param[in] client Identifies the client for which event occurred. 153 * @param[in] evt MQTT event. 154 */ 155 void event_notify(struct mqtt_client *client, const struct mqtt_evt *evt); 156 157 /**@brief Handles MQTT messages received from the peer. 158 * 159 * @param[in] client Identifies the client for which the data was received. 160 161 * @return 0 if the procedure is successful, an error code otherwise. 162 */ 163 int mqtt_handle_rx(struct mqtt_client *client); 164 165 /**@brief Constructs/encodes Connect packet. 166 * 167 * @param[in] client Identifies the client for which the procedure is requested. 168 * All information required for creating the packet like 169 * client id, clean session flag, retain session flag etc are 170 * assumed to be populated for the client instance when this 171 * procedure is requested. 172 * @param[inout] buf_ctx Pointer to the buffer context structure, 173 * containing buffer for the encoded message. 174 * As output points to the beginning and end of 175 * the frame. 176 * 177 * @return 0 if the procedure is successful, an error code otherwise. 178 */ 179 int connect_request_encode(const struct mqtt_client *client, 180 struct buf_ctx *buf); 181 182 /**@brief Constructs/encodes Publish packet. 183 * 184 * @param[in] param Publish message parameters. 185 * @param[inout] buf_ctx Pointer to the buffer context structure, 186 * containing buffer for the encoded message. 187 * As output points to the beginning and end of 188 * the frame. 189 * 190 * @return 0 if the procedure is successful, an error code otherwise. 191 */ 192 int publish_encode(const struct mqtt_publish_param *param, struct buf_ctx *buf); 193 194 /**@brief Constructs/encodes Publish Ack packet. 195 * 196 * @param[in] param Publish Ack message parameters. 197 * @param[inout] buf_ctx Pointer to the buffer context structure, 198 * containing buffer for the encoded message. 199 * As output points to the beginning and end of 200 * the frame. 201 * 202 * @return 0 if the procedure is successful, an error code otherwise. 203 */ 204 int publish_ack_encode(const struct mqtt_puback_param *param, 205 struct buf_ctx *buf); 206 207 /**@brief Constructs/encodes Publish Receive packet. 208 * 209 * @param[in] param Publish Receive message parameters. 210 * @param[inout] buf_ctx Pointer to the buffer context structure, 211 * containing buffer for the encoded message. 212 * As output points to the beginning and end of 213 * the frame. 214 * 215 * @return 0 if the procedure is successful, an error code otherwise. 216 */ 217 int publish_receive_encode(const struct mqtt_pubrec_param *param, 218 struct buf_ctx *buf); 219 220 /**@brief Constructs/encodes Publish Release packet. 221 * 222 * @param[in] param Publish Release message parameters. 223 * @param[inout] buf_ctx Pointer to the buffer context structure, 224 * containing buffer for the encoded message. 225 * As output points to the beginning and end of 226 * the frame. 227 * 228 * @return 0 if the procedure is successful, an error code otherwise. 229 */ 230 int publish_release_encode(const struct mqtt_pubrel_param *param, 231 struct buf_ctx *buf); 232 233 /**@brief Constructs/encodes Publish Complete packet. 234 * 235 * @param[in] param Publish Complete message parameters. 236 * @param[inout] buf_ctx Pointer to the buffer context structure, 237 * containing buffer for the encoded message. 238 * As output points to the beginning and end of 239 * the frame. 240 * 241 * @return 0 if the procedure is successful, an error code otherwise. 242 */ 243 int publish_complete_encode(const struct mqtt_pubcomp_param *param, 244 struct buf_ctx *buf); 245 246 /**@brief Constructs/encodes Disconnect packet. 247 * 248 * @param[inout] buf_ctx Pointer to the buffer context structure, 249 * containing buffer for the encoded message. 250 * As output points to the beginning and end of 251 * the frame. 252 * 253 * @return 0 if the procedure is successful, an error code otherwise. 254 */ 255 int disconnect_encode(struct buf_ctx *buf); 256 257 /**@brief Constructs/encodes Subscribe packet. 258 * 259 * @param[in] param Subscribe message parameters. 260 * @param[inout] buf_ctx Pointer to the buffer context structure, 261 * containing buffer for the encoded message. 262 * As output points to the beginning and end of 263 * the frame. 264 * 265 * @return 0 if the procedure is successful, an error code otherwise. 266 */ 267 int subscribe_encode(const struct mqtt_subscription_list *param, 268 struct buf_ctx *buf); 269 270 /**@brief Constructs/encodes Unsubscribe packet. 271 * 272 * @param[in] param Unsubscribe message parameters. 273 * @param[inout] buf_ctx Pointer to the buffer context structure, 274 * containing buffer for the encoded message. 275 * As output points to the beginning and end of 276 * the frame. 277 * 278 * @return 0 if the procedure is successful, an error code otherwise. 279 */ 280 int unsubscribe_encode(const struct mqtt_subscription_list *param, 281 struct buf_ctx *buf); 282 283 /**@brief Constructs/encodes Ping Request packet. 284 * 285 * @param[inout] buf_ctx Pointer to the buffer context structure, 286 * containing buffer for the encoded message. 287 * As output points to the beginning and end of 288 * the frame. 289 * 290 * @return 0 if the procedure is successful, an error code otherwise. 291 */ 292 int ping_request_encode(struct buf_ctx *buf); 293 294 /**@brief Decode MQTT Packet Type and Length in the MQTT fixed header. 295 * 296 * @param[inout] buf A pointer to the buf_ctx structure containing current 297 * buffer position. 298 * @param[out] type_and_flags Message type and flags. 299 * @param[out] length Length of variable header and payload in the MQTT message. 300 * 301 * @return 0 if the procedure is successful, an error code otherwise. 302 */ 303 int fixed_header_decode(struct buf_ctx *buf, uint8_t *type_and_flags, 304 uint32_t *length); 305 306 /**@brief Decode MQTT Connect Ack packet. 307 * 308 * @param[in] client MQTT client for which packet is decoded. 309 * @param[inout] buf A pointer to the buf_ctx structure containing current 310 * buffer position. 311 * @param[out] param Pointer to buffer for decoded Connect Ack parameters. 312 * 313 * @return 0 if the procedure is successful, an error code otherwise. 314 */ 315 int connect_ack_decode(const struct mqtt_client *client, struct buf_ctx *buf, 316 struct mqtt_connack_param *param); 317 318 /**@brief Decode MQTT Publish packet. 319 * 320 * @param[in] flags Byte containing message type and flags. 321 * @param[in] var_length Length of the variable part of the message. 322 * @param[inout] buf A pointer to the buf_ctx structure containing current 323 * buffer position. 324 * @param[out] param Pointer to buffer for decoded Publish parameters. 325 * 326 * @return 0 if the procedure is successful, an error code otherwise. 327 */ 328 int publish_decode(uint8_t flags, uint32_t var_length, struct buf_ctx *buf, 329 struct mqtt_publish_param *param); 330 331 /**@brief Decode MQTT Publish Ack packet. 332 * 333 * @param[inout] buf A pointer to the buf_ctx structure containing current 334 * buffer position. 335 * @param[out] param Pointer to buffer for decoded Publish Ack parameters. 336 * 337 * @return 0 if the procedure is successful, an error code otherwise. 338 */ 339 int publish_ack_decode(struct buf_ctx *buf, struct mqtt_puback_param *param); 340 341 /**@brief Decode MQTT Publish Receive packet. 342 * 343 * @param[inout] buf A pointer to the buf_ctx structure containing current 344 * buffer position. 345 * @param[out] param Pointer to buffer for decoded Publish Receive parameters. 346 * 347 * @return 0 if the procedure is successful, an error code otherwise. 348 */ 349 int publish_receive_decode(struct buf_ctx *buf, 350 struct mqtt_pubrec_param *param); 351 352 /**@brief Decode MQTT Publish Release packet. 353 * 354 * @param[inout] buf A pointer to the buf_ctx structure containing current 355 * buffer position. 356 * @param[out] param Pointer to buffer for decoded Publish Release parameters. 357 * 358 * @return 0 if the procedure is successful, an error code otherwise. 359 */ 360 int publish_release_decode(struct buf_ctx *buf, 361 struct mqtt_pubrel_param *param); 362 363 /**@brief Decode MQTT Publish Complete packet. 364 * 365 * @param[inout] buf A pointer to the buf_ctx structure containing current 366 * buffer position. 367 * @param[out] param Pointer to buffer for decoded Publish Complete parameters. 368 * 369 * @return 0 if the procedure is successful, an error code otherwise. 370 */ 371 int publish_complete_decode(struct buf_ctx *buf, 372 struct mqtt_pubcomp_param *param); 373 374 /**@brief Decode MQTT Subscribe packet. 375 * 376 * @param[inout] buf A pointer to the buf_ctx structure containing current 377 * buffer position. 378 * @param[out] param Pointer to buffer for decoded Subscribe parameters. 379 * 380 * @return 0 if the procedure is successful, an error code otherwise. 381 */ 382 int subscribe_ack_decode(struct buf_ctx *buf, 383 struct mqtt_suback_param *param); 384 385 /**@brief Decode MQTT Unsubscribe packet. 386 * 387 * @param[inout] buf A pointer to the buf_ctx structure containing current 388 * buffer position. 389 * @param[out] param Pointer to buffer for decoded Unsubscribe parameters. 390 * 391 * @return 0 if the procedure is successful, an error code otherwise. 392 */ 393 int unsubscribe_ack_decode(struct buf_ctx *buf, 394 struct mqtt_unsuback_param *param); 395 396 #ifdef __cplusplus 397 } 398 #endif 399 400 #endif /* MQTT_INTERNAL_H_ */ 401