-
Notifications
You must be signed in to change notification settings - Fork 33
/
lwmqtt.h
427 lines (384 loc) · 13.8 KB
/
lwmqtt.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
#ifndef LWMQTT_H
#define LWMQTT_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
/**
* The error type used by all exposed APIs.
*
* If a function returns an error that operates on a connected client (e.g publish, keep_alive, etc.) the caller should
* switch into a disconnected state, close and cleanup the current connection and start over by creating a new
* connection.
*/
typedef enum {
LWMQTT_SUCCESS = 0,
LWMQTT_BUFFER_TOO_SHORT = -1,
LWMQTT_VARNUM_OVERFLOW = -2,
LWMQTT_NETWORK_FAILED_CONNECT = -3,
LWMQTT_NETWORK_TIMEOUT = -4,
LWMQTT_NETWORK_FAILED_READ = -5,
LWMQTT_NETWORK_FAILED_WRITE = -6,
LWMQTT_REMAINING_LENGTH_OVERFLOW = -7,
LWMQTT_REMAINING_LENGTH_MISMATCH = -8,
LWMQTT_MISSING_OR_WRONG_PACKET = -9,
LWMQTT_CONNECTION_DENIED = -10,
LWMQTT_FAILED_SUBSCRIPTION = -11,
LWMQTT_SUBACK_ARRAY_OVERFLOW = -12,
LWMQTT_PONG_TIMEOUT = -13,
} lwmqtt_err_t;
/**
* The common string object.
*/
typedef struct {
uint16_t len;
char *data;
} lwmqtt_string_t;
/**
* The default initializer for string objects.
*/
#define lwmqtt_default_string \
{ 0, NULL }
/**
* Returns a string object for the passed C string.
*
* @param str The C string.
* @return A string object.
*/
lwmqtt_string_t lwmqtt_string(const char *str);
/**
* Compares a string object to a C string.
*
* @param a The string object to compare.
* @param b The C string to compare.
* @return Similarity e.g. strcmp().
*/
int lwmqtt_strcmp(lwmqtt_string_t a, const char *b);
/**
* The available QOS levels.
*/
typedef enum {
LWMQTT_QOS0 = 0,
LWMQTT_QOS1 = 1,
LWMQTT_QOS2 = 2,
LWMQTT_QOS_FAILURE = 128,
} lwmqtt_qos_t;
/**
* The common message object.
*/
typedef struct {
lwmqtt_qos_t qos;
bool retained;
uint8_t *payload;
size_t payload_len;
} lwmqtt_message_t;
/**
* The default initializer for message objects.
*/
#define lwmqtt_default_message \
{ LWMQTT_QOS0, false, NULL, 0 }
/**
* The object defining the last will of a client.
*/
typedef struct {
lwmqtt_string_t topic;
lwmqtt_qos_t qos;
bool retained;
lwmqtt_string_t payload;
} lwmqtt_will_t;
/**
* The default initializer for will objects.
*/
#define lwmqtt_default_will \
{ lwmqtt_default_string, LWMQTT_QOS0, false, lwmqtt_default_string }
/**
* The available return codes transported by the connack packet.
*/
typedef enum {
LWMQTT_CONNECTION_ACCEPTED = 0,
LWMQTT_UNACCEPTABLE_PROTOCOL = 1,
LWMQTT_IDENTIFIER_REJECTED = 2,
LWMQTT_SERVER_UNAVAILABLE = 3,
LWMQTT_BAD_USERNAME_OR_PASSWORD = 4,
LWMQTT_NOT_AUTHORIZED = 5,
LWMQTT_UNKNOWN_RETURN_CODE = 6
} lwmqtt_return_code_t;
/**
* The object containing the connection options.
*/
typedef struct {
lwmqtt_string_t client_id;
uint16_t keep_alive;
bool clean_session;
lwmqtt_string_t username;
lwmqtt_string_t password;
lwmqtt_return_code_t return_code;
bool session_present;
} lwmqtt_connect_options_t;
/**
* The default initializer for the connect options objects.
*/
#define lwmqtt_default_connect_options \
{ lwmqtt_default_string, 60, true, lwmqtt_default_string, lwmqtt_default_string, LWMQTT_UNKNOWN_RETURN_CODE, false }
/**
* The object containing the publish options.
*/
typedef struct {
uint16_t *dup_id;
bool skip_ack;
} lwmqtt_publish_options_t;
/**
* The default initializer for publish options object.
*/
#define lwmqtt_default_publish_options \
{ NULL, false }
/**
* Forward declaration of the client object.
*/
typedef struct lwmqtt_client_t lwmqtt_client_t;
/**
* The callback used to read from a network object.
*
* The callbacks is expected to read up to the amount of bytes in to the passed buffer. It should block the specified
* timeout and wait for more incoming data.
*
* @param ref A custom reference.
* @param buf The buffer.
* @param len The length of the buffer.
* @param read Variable that must be set with the amount of read bytes.
* @param timeout The timeout in milliseconds for the operation.
*/
typedef lwmqtt_err_t (*lwmqtt_network_read_t)(void *ref, uint8_t *buf, size_t len, size_t *read, uint32_t timeout);
/**
* The callback used to write to a network object.
*
* The callback is expected to write up to the amount of bytes from the passed buffer. It should wait up to the
* specified timeout to write the specified data to the network.
*
* @param ref A custom reference.
* @param buf The buffer.
* @param len The length of the buffer.
* @param sent Variable that must be set with the amount of written bytes.
* @param timeout The timeout in milliseconds for the operation.
*/
typedef lwmqtt_err_t (*lwmqtt_network_write_t)(void *ref, uint8_t *buf, size_t len, size_t *sent, uint32_t timeout);
/**
* The callback used to set a timer.
*
* @param ref A custom reference.
* @param timeout The amount of milliseconds until the deadline.
*/
typedef void (*lwmqtt_timer_set_t)(void *ref, uint32_t timeout);
/**
* The callback used to get a timers value.
*
* @param ref A custom reference.
* @return The amount of milliseconds until the deadline. May return negative numbers if the deadline has been reached.
*/
typedef int32_t (*lwmqtt_timer_get_t)(void *ref);
/**
* The callback used to forward incoming messages.
*
* Note: The callback is mostly executed because of a call to lwmqtt_yield() that processes incoming messages. However,
* it is possible that the callback is also executed during a call to lwmqtt_subscribe(), lwmqtt_publish() or
* lwmqtt_unsubscribe() if incoming messages are received between the required acknowledgements. It is therefore not
* recommended to call any further lwmqtt methods in the callback as this might result in deadlocks. Instead, the
* callback should place the received messages in a queue and dispatch them after the caller has returned.
*
* @param client The client object.
* @param ref A custom reference.
* @param str The topic string.
* @param msg The received message.
*/
typedef void (*lwmqtt_callback_t)(lwmqtt_client_t *client, void *ref, lwmqtt_string_t str, lwmqtt_message_t msg);
/**
* The client object.
*/
struct lwmqtt_client_t {
uint16_t last_packet_id;
uint32_t keep_alive_interval;
bool pong_pending;
size_t write_buf_size, read_buf_size;
uint8_t *write_buf, *read_buf;
lwmqtt_callback_t callback;
void *callback_ref;
void *network;
lwmqtt_network_read_t network_read;
lwmqtt_network_write_t network_write;
void *keep_alive_timer;
void *command_timer;
lwmqtt_timer_set_t timer_set;
lwmqtt_timer_get_t timer_get;
bool drop_overflow;
uint32_t *overflow_counter;
};
/**
* Will initialize the specified client object.
*
* @param client The client object.
* @param write_buf The write buffer.
* @param write_buf_size The write buffer size.
* @param read_buf The read buffer.
* @param read_buf_size The read buffer size.
*/
void lwmqtt_init(lwmqtt_client_t *client, uint8_t *write_buf, size_t write_buf_size, uint8_t *read_buf,
size_t read_buf_size);
/**
* Will set the network reference and callbacks for this client object.
*
* @param client The client object.
* @param ref The reference to the network object.
* @param read The read callback.
* @param write The write callback.
*/
void lwmqtt_set_network(lwmqtt_client_t *client, void *ref, lwmqtt_network_read_t read, lwmqtt_network_write_t write);
/**
* Will set the timer references and callbacks for this client object.
*
* @param client The client object.
* @param keep_alive_timer The reference to the keep alive timer.
* @param command_timer The reference to the command timer.
* @param set The set callback.
* @param get The get callback.
*/
void lwmqtt_set_timers(lwmqtt_client_t *client, void *keep_alive_timer, void *command_timer, lwmqtt_timer_set_t set,
lwmqtt_timer_get_t get);
/**
* Will set the callback used to receive incoming messages.
*
* @param client The client object.
* @param ref A custom reference that will passed to the callback.
* @param cb The callback to be called.
*/
void lwmqtt_set_callback(lwmqtt_client_t *client, void *ref, lwmqtt_callback_t cb);
/**
* Will configure the client to drop packets that overflow the read buffer. If a counter is provided it will be
* incremented with each dropped packet.
*
* @param client The client.
* @param enabled Whether dropping is enabled.
* @param counter The dropped packet counter.
*/
void lwmqtt_drop_overflow(lwmqtt_client_t *client, bool enabled, uint32_t *counter);
/**
* Will send a connect packet and wait for a connack response. If options are provided they are used for the
* connection attempt and the return code and whether a session was present is stored in it.
*
* The network object must already be connected to the server. An error is returned if the broker rejects the
* connection.
*
* @param client The client object.
* @param options The optional connect options.
* @param will The will object.
* @param timeout The command timeout.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_connect(lwmqtt_client_t *client, lwmqtt_connect_options_t *options, lwmqtt_will_t *will,
uint32_t timeout);
/**
* Will send a publish packet and wait for all acks to complete. If the encoded packet (without payload) is bigger than
* the write buffer the function will return LWMQTT_BUFFER_TOO_SHORT without attempting to send the packet.
*
* If options.dup_id is present and zero, the client will store the used packet id at the specified location (QoS >= 1).
* If options.dup_id is present and non-zero, the client will use the specified number as the packet id and flag the
* message as a duplicate (QoS >= 1).
*
* Note: The message callback might be called with incoming messages as part of this call.
*
* @param client The client object.
* @param options The optional publish options.
* @param topic The topic.
* @param msg The message.
* @param timeout The command timeout.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_publish(lwmqtt_client_t *client, lwmqtt_publish_options_t *options, lwmqtt_string_t topic,
lwmqtt_message_t msg, uint32_t timeout);
/**
* Will send a subscribe packet with multiple topic filters plus QOS levels and wait for the suback to complete.
*
* Note: The message callback might be called with incoming messages as part of this call.
*
* @param client The client object.
* @param count The number of topic filters and QOS levels.
* @param topic_filter The list of topic filters.
* @param qos The list of QOS levels.
* @param timeout The command timeout.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_subscribe(lwmqtt_client_t *client, int count, lwmqtt_string_t *topic_filter, lwmqtt_qos_t *qos,
uint32_t timeout);
/**
* Will send a subscribe packet with a single topic filter plus QOS level and wait for the suback to complete.
*
* Note: The message callback might be called with incoming messages as part of this call.
*
* @param client The client object.
* @param topic_filter The topic filter.
* @param qos The QOS level.
* @param timeout The command timeout.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_subscribe_one(lwmqtt_client_t *client, lwmqtt_string_t topic_filter, lwmqtt_qos_t qos,
uint32_t timeout);
/**
* Will send an unsubscribe packet with multiple topic filters and wait for the unsuback to complete.
*
* Note: The message callback might be called with incoming messages as part of this call.
*
* @param client The client object.
* @param count The number of topic filters.
* @param topic_filter The topic filter.
* @param timeout The command timeout.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_unsubscribe(lwmqtt_client_t *client, int count, lwmqtt_string_t *topic_filter, uint32_t timeout);
/**
* Will send an unsubscribe packet with a single topic filter and wait for the unsuback to complete.
*
* Note: The message callback might be called with incoming messages as part of this call.
*
* @param client The client object.
* @param topic_filter The topic filter.
* @param timeout The command timeout.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_unsubscribe_one(lwmqtt_client_t *client, lwmqtt_string_t topic_filter, uint32_t timeout);
/**
* Will send a disconnect packet and finish the client.
*
* @param client The client object.
* @param timeout The command timeout.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_disconnect(lwmqtt_client_t *client, uint32_t timeout);
/**
* Will yield control to the client and receive incoming packets from the network.
*
* Single-threaded applications may peek on the network and assess if data is available to read before calling yield and
* potentially block until the timeout is reached. Multi-threaded applications may select on the socket and block until
* data is available and then yield to the client if data is available. All applications may specify the amount of bytes
* available to read in order to constrain the yield to only receive packets that are already in-flight.
*
* If no availability info is given the yield will return after one packet has been successfully read or the deadline
* has been reached but no single byte has been received.
*
* Note: The message callback might be called with incoming messages as part of this call.
*
* @param client The client object.
* @param available The available bytes to read.
* @param timeout The command timeout.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_yield(lwmqtt_client_t *client, size_t available, uint32_t timeout);
/**
* Will yield control to the client to keep the connection alive.
*
* This functions must be called at a rate slightly lower than 25% of the configured keep alive. If keep alive is zero,
* the function may not be called at all.
*
* @param client The client object.
* @param timeout The command timeout.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_keep_alive(lwmqtt_client_t *client, uint32_t timeout);
#endif // LWMQTT_H