-
Notifications
You must be signed in to change notification settings - Fork 375
/
liblwm2m.h
885 lines (779 loc) · 35.3 KB
/
liblwm2m.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
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
/*******************************************************************************
*
* Copyright (c) 2013, 2014 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v20.html
* The Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* David Navarro, Intel Corporation - initial API and implementation
* Fabien Fleutot - Please refer to git log
* Simon Bernard - Please refer to git log
* Toby Jaffey - Please refer to git log
* Julien Vermillard - Please refer to git log
* Bosch Software Innovations GmbH - Please refer to git log
* Pascal Rieux - Please refer to git log
* Ville Skyttä - Please refer to git log
* Scott Bertin, AMETEK, Inc. - Please refer to git log
* Tuve Nordius, Husqvarna Group - Please refer to git log
*
*******************************************************************************/
/*
Copyright (c) 2013, 2014 Intel Corporation
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.
David Navarro <david.navarro@intel.com>
*/
#ifndef _LWM2M_CLIENT_H_
#define _LWM2M_CLIENT_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <time.h>
#ifdef LWM2M_SERVER_MODE
#ifndef LWM2M_SUPPORT_JSON
#define LWM2M_SUPPORT_JSON
#endif
#ifndef LWM2M_VERSION_1_0
#ifndef LWM2M_SUPPORT_SENML_JSON
#define LWM2M_SUPPORT_SENML_JSON
#endif
#endif
#endif
#ifdef LWM2M_BOOTSTRAP_SERVER_MODE
#ifndef LWM2M_VERSION_1_0
#ifndef LWM2M_SUPPORT_SENML_JSON
#define LWM2M_SUPPORT_SENML_JSON
#endif
#endif
#endif
#ifndef LWM2M_SUPPORT_TLV
#if defined(LWM2M_VERSION_1_0) || defined(LWM2M_SERVER_MODE) || defined(LWM2M_BOOTSTRAP_SERVER_MODE)
/* TLV is mandatory for LWM2M 1.0 client and server. */
/* TLV is mandatory for LWM2M 1.1 server. */
#define LWM2M_SUPPORT_TLV
#endif
#endif
#if defined(LWM2M_BOOTSTRAP) && defined(LWM2M_BOOTSTRAP_SERVER_MODE)
#error "LWM2M_BOOTSTRAP and LWM2M_BOOTSTRAP_SERVER_MODE cannot be defined at the same time!"
#endif
/*
* Platform abstraction functions to be implemented by the user
*/
#ifndef LWM2M_MEMORY_TRACE
// Allocate a block of size bytes of memory, returning a pointer to the beginning of the block.
void * lwm2m_malloc(size_t s);
// Deallocate a block of memory previously allocated by lwm2m_malloc() or lwm2m_strdup()
void lwm2m_free(void * p);
// Allocate a memory block, duplicate the string str in it and return a pointer to this new block.
char * lwm2m_strdup(const char * str);
#else
// same functions as above with caller location for debugging purposes
char * lwm2m_trace_strdup(const char * str, const char * file, const char * function, int lineno);
void * lwm2m_trace_malloc(size_t size, const char * file, const char * function, int lineno);
void lwm2m_trace_free(void * mem, const char * file, const char * function, int lineno);
#define lwm2m_strdup(S) lwm2m_trace_strdup(S, __FILE__, __FUNCTION__, __LINE__)
#define lwm2m_malloc(S) lwm2m_trace_malloc(S, __FILE__, __FUNCTION__, __LINE__)
#define lwm2m_free(M) lwm2m_trace_free(M, __FILE__, __FUNCTION__, __LINE__)
#endif
// Compare at most the n first bytes of s1 and s2, return 0 if they match
int lwm2m_strncmp(const char * s1, const char * s2, size_t n);
int lwm2m_strcasecmp(const char * str1, const char * str2);
// This function must return the number of seconds elapsed since origin.
// The origin (Epoch, system boot, etc...) does not matter as this
// function is used only to determine the elapsed time since the last
// call to it.
// In case of error, this must return a negative value.
// Per POSIX specifications, time_t is a signed integer.
time_t lwm2m_gettime(void);
#ifdef LWM2M_WITH_LOGS
// Same usage as C89 printf()
void lwm2m_printf(const char * format, ...);
#endif
typedef struct _lwm2m_context_ lwm2m_context_t;
// communication layer
#ifdef LWM2M_CLIENT_MODE
// Returns a session handle that MUST uniquely identify a peer.
// contextP: Pointer to the LWM2M context
// secObjInstID: ID of the Securty Object instance to open a connection to
// userData: parameter to lwm2m_init()
void * lwm2m_connect_server(uint16_t secObjInstID, void * userData);
// Close a session created by lwm2m_connect_server()
// sessionH: session handle identifying the peer (opaque to the core)
// userData: parameter to lwm2m_init()
void lwm2m_close_connection(void * sessionH, void * userData);
#endif
// Send data to a peer
// Returns COAP_NO_ERROR or a COAP_NNN error code
// sessionH: session handle identifying the peer (opaque to the core)
// buffer, length: data to send
// userData: parameter to lwm2m_init()
uint8_t lwm2m_buffer_send(void * sessionH, uint8_t * buffer, size_t length, void * userData);
// Compare two session handles
// Returns true if the two sessions identify the same peer. false otherwise.
// userData: parameter to lwm2m_init()
bool lwm2m_session_is_equal(void * session1, void * session2, void * userData);
/*
* Error code
*/
#define COAP_NO_ERROR (uint8_t)0x00
#define COAP_IGNORE (uint8_t)0x01
#define COAP_RETRANSMISSION (uint8_t)0x02
#define COAP_201_CREATED (uint8_t)0x41
#define COAP_202_DELETED (uint8_t)0x42
#define COAP_204_CHANGED (uint8_t)0x44
#define COAP_205_CONTENT (uint8_t)0x45
#define COAP_231_CONTINUE (uint8_t)0x5F
#define COAP_400_BAD_REQUEST (uint8_t)0x80
#define COAP_401_UNAUTHORIZED (uint8_t)0x81
#define COAP_402_BAD_OPTION (uint8_t)0x82
#define COAP_404_NOT_FOUND (uint8_t)0x84
#define COAP_405_METHOD_NOT_ALLOWED (uint8_t)0x85
#define COAP_406_NOT_ACCEPTABLE (uint8_t)0x86
#define COAP_408_REQ_ENTITY_INCOMPLETE (uint8_t)0x88
#define COAP_412_PRECONDITION_FAILED (uint8_t)0x8C
#define COAP_413_ENTITY_TOO_LARGE (uint8_t)0x8D
#define COAP_500_INTERNAL_SERVER_ERROR (uint8_t)0xA0
#define COAP_501_NOT_IMPLEMENTED (uint8_t)0xA1
#define COAP_503_SERVICE_UNAVAILABLE (uint8_t)0xA3
/*
* Standard Object IDs
*/
#define LWM2M_SECURITY_OBJECT_ID 0
#define LWM2M_SERVER_OBJECT_ID 1
#define LWM2M_ACL_OBJECT_ID 2
#define LWM2M_DEVICE_OBJECT_ID 3
#define LWM2M_CONN_MONITOR_OBJECT_ID 4
#define LWM2M_FIRMWARE_UPDATE_OBJECT_ID 5
#define LWM2M_LOCATION_OBJECT_ID 6
#define LWM2M_CONN_STATS_OBJECT_ID 7
#define LWM2M_OSCORE_OBJECT_ID 21
/*
* Resource IDs for the LWM2M Security Object
*/
#define LWM2M_SECURITY_URI_ID 0
#define LWM2M_SECURITY_BOOTSTRAP_ID 1
#define LWM2M_SECURITY_SECURITY_ID 2
#define LWM2M_SECURITY_PUBLIC_KEY_ID 3
#define LWM2M_SECURITY_SERVER_PUBLIC_KEY_ID 4
#define LWM2M_SECURITY_SECRET_KEY_ID 5
#define LWM2M_SECURITY_SMS_SECURITY_ID 6
#define LWM2M_SECURITY_SMS_KEY_PARAM_ID 7
#define LWM2M_SECURITY_SMS_SECRET_KEY_ID 8
#define LWM2M_SECURITY_SMS_SERVER_NUMBER_ID 9
#define LWM2M_SECURITY_SHORT_SERVER_ID 10
#define LWM2M_SECURITY_HOLD_OFF_ID 11
#define LWM2M_SECURITY_BOOTSTRAP_TIMEOUT_ID 12
/*
* Resource IDs for the LWM2M Server Object
*/
#define LWM2M_SERVER_SHORT_ID_ID 0
#define LWM2M_SERVER_LIFETIME_ID 1
#define LWM2M_SERVER_MIN_PERIOD_ID 2
#define LWM2M_SERVER_MAX_PERIOD_ID 3
#define LWM2M_SERVER_DISABLE_ID 4
#define LWM2M_SERVER_TIMEOUT_ID 5
#define LWM2M_SERVER_STORING_ID 6
#define LWM2M_SERVER_BINDING_ID 7
#define LWM2M_SERVER_UPDATE_ID 8
#define LWM2M_SERVER_BOOTSTRAP_ID 9
#define LWM2M_SERVER_APN_ID 10
#define LWM2M_SERVER_TLS_ALERT_CODE_ID 11
#define LWM2M_SERVER_LAST_BOOTSTRAP_ID 12
#define LWM2M_SERVER_REG_ORDER_ID 13
#define LWM2M_SERVER_INITIAL_REG_DELAY_ID 14
#define LWM2M_SERVER_REG_FAIL_BLOCK_ID 15
#define LWM2M_SERVER_REG_FAIL_BOOTSTRAP_ID 16
#define LWM2M_SERVER_COMM_RETRY_COUNT_ID 17
#define LWM2M_SERVER_COMM_RETRY_TIMER_ID 18
#define LWM2M_SERVER_SEQ_DELAY_TIMER_ID 19
#define LWM2M_SERVER_SEQ_RETRY_COUNT_ID 20
#define LWM2M_SERVER_TRIGGER_ID 21
#define LWM2M_SERVER_PREFERRED_TRANSPORT_ID 22
#define LWM2M_SERVER_MUTE_SEND_ID 23
#define LWM2M_SECURITY_MODE_PRE_SHARED_KEY 0
#define LWM2M_SECURITY_MODE_RAW_PUBLIC_KEY 1
#define LWM2M_SECURITY_MODE_CERTIFICATE 2
#define LWM2M_SECURITY_MODE_NONE 3
/*
* Utility functions for sorted linked list
*/
typedef struct _lwm2m_list_t
{
struct _lwm2m_list_t * next;
uint16_t id;
} lwm2m_list_t;
// defined in list.c
// Add 'node' to the list 'head' and return the new list
lwm2m_list_t * lwm2m_list_add(lwm2m_list_t * head, lwm2m_list_t * node);
// Return the node with ID 'id' from the list 'head' or NULL if not found
lwm2m_list_t * lwm2m_list_find(lwm2m_list_t * head, uint16_t id);
// Remove the node with ID 'id' from the list 'head' and return the new list
lwm2m_list_t * lwm2m_list_remove(lwm2m_list_t * head, uint16_t id, lwm2m_list_t ** nodeP);
// Return the lowest unused ID in the list 'head'
uint16_t lwm2m_list_newId(lwm2m_list_t * head);
// Free a list. Do not use if nodes contain allocated pointers as it calls lwm2m_free on nodes only.
// If the nodes of the list need to do more than just "free()" their instances, don't use lwm2m_list_free().
void lwm2m_list_free(lwm2m_list_t * head);
#define LWM2M_LIST_ADD(H,N) lwm2m_list_add((lwm2m_list_t *)H, (lwm2m_list_t *)N);
#define LWM2M_LIST_RM(H,I,N) lwm2m_list_remove((lwm2m_list_t *)H, I, (lwm2m_list_t **)N);
#define LWM2M_LIST_FIND(H,I) lwm2m_list_find((lwm2m_list_t *)H, I)
#define LWM2M_LIST_FREE(H) lwm2m_list_free((lwm2m_list_t *)H)
/*
* Helper functions for CoAP block size settings.
*/
bool lwm2m_set_coap_block_size(uint16_t coap_block_size_arg);
uint16_t lwm2m_get_coap_block_size(void);
/*
* URI
*
* objectId is always set
* instanceId or resourceId are set according to the flag bit-field
*
*/
#define LWM2M_MAX_ID ((uint16_t)0xFFFF)
#define LWM2M_URI_IS_SET_OBJECT(uri) ((uri)->objectId != LWM2M_MAX_ID)
#define LWM2M_URI_IS_SET_INSTANCE(uri) ((uri)->instanceId != LWM2M_MAX_ID)
#define LWM2M_URI_IS_SET_RESOURCE(uri) ((uri)->resourceId != LWM2M_MAX_ID)
#ifndef LWM2M_VERSION_1_0
#define LWM2M_URI_IS_SET_RESOURCE_INSTANCE(uri) ((uri)->resourceInstanceId != LWM2M_MAX_ID)
#endif
typedef struct
{
uint16_t objectId;
uint16_t instanceId;
uint16_t resourceId;
#ifndef LWM2M_VERSION_1_0
uint16_t resourceInstanceId;
#endif
} lwm2m_uri_t;
#define LWM2M_URI_RESET(uri) memset((uri), 0xFF, sizeof(lwm2m_uri_t))
#define LWM2M_STRING_ID_MAX_LEN 6
// Parse an URI in LWM2M format and fill the lwm2m_uri_t.
// Return the number of characters read from buffer or 0 in case of error.
// Valid URIs: /1, /1/, /1/2, /1/2/, /1/2/3
// Invalid URIs: /, //, //2, /1//, /1//3, /1/2/3/, /1/2/3/4
int lwm2m_stringToUri(const char * buffer, size_t buffer_len, lwm2m_uri_t * uriP);
/*
* The lwm2m_data_t is used to store LWM2M resource values in a hierarchical way.
* Depending on the type the value is different:
* - LWM2M_TYPE_OBJECT, LWM2M_TYPE_OBJECT_INSTANCE, LWM2M_TYPE_MULTIPLE_RESOURCE: value.asChildren
* - LWM2M_TYPE_STRING, LWM2M_TYPE_OPAQUE, LWM2M_TYPE_CORE_LINK: value.asBuffer
* - LWM2M_TYPE_INTEGER, LWM2M_TYPE_TIME: value.asInteger
* - LWM2M_TYPE_UNSIGNED_INTEGER: value.asUnsigned
* - LWM2M_TYPE_FLOAT: value.asFloat
* - LWM2M_TYPE_BOOLEAN: value.asBoolean
*
* LWM2M_TYPE_STRING is also used when the data is in text format.
*/
typedef enum
{
LWM2M_TYPE_UNDEFINED = 0,
LWM2M_TYPE_OBJECT,
LWM2M_TYPE_OBJECT_INSTANCE,
LWM2M_TYPE_MULTIPLE_RESOURCE,
LWM2M_TYPE_STRING,
LWM2M_TYPE_OPAQUE,
LWM2M_TYPE_INTEGER,
LWM2M_TYPE_UNSIGNED_INTEGER,
LWM2M_TYPE_FLOAT,
LWM2M_TYPE_BOOLEAN,
LWM2M_TYPE_OBJECT_LINK,
LWM2M_TYPE_CORE_LINK
} lwm2m_data_type_t;
typedef struct _lwm2m_data_t lwm2m_data_t;
struct _lwm2m_data_t
{
lwm2m_data_type_t type;
uint16_t id;
union
{
bool asBoolean;
int64_t asInteger;
uint64_t asUnsigned;
double asFloat;
struct
{
size_t length;
uint8_t * buffer;
} asBuffer;
struct
{
size_t count;
lwm2m_data_t * array;
} asChildren;
struct
{
uint16_t objectId;
uint16_t objectInstanceId;
} asObjLink;
} value;
};
typedef enum
{
LWM2M_CONTENT_TEXT = 0, // Also used as undefined
LWM2M_CONTENT_LINK = 40,
LWM2M_CONTENT_OPAQUE = 42,
LWM2M_CONTENT_TLV_OLD = 1542, // Keep old value for backward-compatibility
LWM2M_CONTENT_TLV = 11542,
LWM2M_CONTENT_JSON_OLD = 1543, // Keep old value for backward-compatibility
LWM2M_CONTENT_JSON = 11543,
LWM2M_CONTENT_SENML_JSON = 110
} lwm2m_media_type_t;
lwm2m_data_t * lwm2m_data_new(int size);
int lwm2m_data_parse(lwm2m_uri_t * uriP, const uint8_t * buffer, size_t bufferLen, lwm2m_media_type_t format, lwm2m_data_t ** dataP);
int lwm2m_data_serialize(lwm2m_uri_t * uriP, int size, lwm2m_data_t * dataP, lwm2m_media_type_t * formatP, uint8_t ** bufferP);
void lwm2m_data_free(int size, lwm2m_data_t * dataP);
void lwm2m_data_encode_string(const char * string, lwm2m_data_t * dataP);
void lwm2m_data_encode_nstring(const char * string, size_t length, lwm2m_data_t * dataP);
void lwm2m_data_encode_opaque(const uint8_t * buffer, size_t length, lwm2m_data_t * dataP);
void lwm2m_data_encode_int(int64_t value, lwm2m_data_t * dataP);
int lwm2m_data_decode_int(const lwm2m_data_t * dataP, int64_t * valueP);
void lwm2m_data_encode_uint(uint64_t value, lwm2m_data_t * dataP);
int lwm2m_data_decode_uint(const lwm2m_data_t * dataP, uint64_t * valueP);
void lwm2m_data_encode_float(double value, lwm2m_data_t * dataP);
int lwm2m_data_decode_float(const lwm2m_data_t * dataP, double * valueP);
void lwm2m_data_encode_bool(bool value, lwm2m_data_t * dataP);
int lwm2m_data_decode_bool(const lwm2m_data_t * dataP, bool * valueP);
void lwm2m_data_encode_objlink(uint16_t objectId, uint16_t objectInstanceId, lwm2m_data_t * dataP);
void lwm2m_data_encode_corelink(const char * corelink, lwm2m_data_t * dataP);
void lwm2m_data_encode_instances(lwm2m_data_t * subDataP, size_t count, lwm2m_data_t * dataP);
void lwm2m_data_include(lwm2m_data_t * subDataP, size_t count, lwm2m_data_t * dataP);
/*
* Utility function to parse TLV buffers directly
*
* Returned value: number of bytes parsed
* buffer: buffer to parse
* buffer_len: length in bytes of buffer
* oType: (OUT) type of the parsed TLV record. can be:
* - LWM2M_TYPE_OBJECT
* - LWM2M_TYPE_OBJECT_INSTANCE
* - LWM2M_TYPE_MULTIPLE_RESOURCE
* - LWM2M_TYPE_OPAQUE
* oID: (OUT) ID of the parsed TLV record
* oDataIndex: (OUT) index of the data of the parsed TLV record in the buffer
* oDataLen: (OUT) length of the data of the parsed TLV record
*/
#define LWM2M_TLV_HEADER_MAX_LENGTH 6
int lwm2m_decode_TLV(const uint8_t * buffer, size_t buffer_len, lwm2m_data_type_t * oType, uint16_t * oID, size_t * oDataIndex, size_t * oDataLen);
/*
* LWM2M Objects
*
* For the read callback, if *numDataP is not zero, *dataArrayP is pre-allocated
* and contains the list of resources to read.
*
*/
typedef struct _lwm2m_object_t lwm2m_object_t;
typedef enum
{
LWM2M_WRITE_PARTIAL_UPDATE, // Write should add or update resources and resource instances.
LWM2M_WRITE_REPLACE_RESOURCES, // Write should replace resources entirely.
LWM2M_WRITE_REPLACE_INSTANCE, // Write should replace the entire instance.
} lwm2m_write_type_t;
typedef uint8_t (*lwm2m_read_callback_t) (lwm2m_context_t * contextP, uint16_t instanceId, int * numDataP, lwm2m_data_t ** dataArrayP, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_discover_callback_t) (lwm2m_context_t * contextP, uint16_t instanceId, int * numDataP, lwm2m_data_t ** dataArrayP, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_write_callback_t) (lwm2m_context_t * contextP, uint16_t instanceId, int numData, lwm2m_data_t * dataArray, lwm2m_object_t * objectP, lwm2m_write_type_t writeType);
typedef uint8_t (*lwm2m_execute_callback_t) (lwm2m_context_t * contextP, uint16_t instanceId, uint16_t resourceId, uint8_t * buffer, int length, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_create_callback_t) (lwm2m_context_t * contextP, uint16_t instanceId, int numData, lwm2m_data_t * dataArray, lwm2m_object_t * objectP);
#ifdef LWM2M_RAW_BLOCK1_REQUESTS
typedef uint8_t (*lwm2m_raw_block1_create_callback_t) (lwm2m_context_t * contextP, lwm2m_uri_t * uriP, lwm2m_media_type_t format, uint8_t * buffer, int length, lwm2m_object_t * objectP, uint32_t block_num, uint8_t block_more);
typedef uint8_t (*lwm2m_raw_block1_write_callback_t) (lwm2m_context_t * contextP, lwm2m_uri_t * uriP, lwm2m_media_type_t format, uint8_t * buffer, int length, lwm2m_object_t * objectP, uint32_t block_num, uint8_t block_more);
typedef uint8_t (*lwm2m_raw_block1_execute_callback_t) (lwm2m_context_t * contextP, lwm2m_uri_t * uriP, uint8_t * buffer, int length, lwm2m_object_t * objectP, uint32_t block_num, uint8_t block_more);
#endif
typedef uint8_t (*lwm2m_delete_callback_t) (lwm2m_context_t * contextP, uint16_t instanceId, lwm2m_object_t * objectP);
struct _lwm2m_object_t
{
struct _lwm2m_object_t * next; // for internal use only.
uint16_t objID;
uint8_t versionMajor;
uint8_t versionMinor;
lwm2m_list_t * instanceList;
lwm2m_read_callback_t readFunc;
lwm2m_write_callback_t writeFunc;
lwm2m_execute_callback_t executeFunc;
lwm2m_create_callback_t createFunc;
#ifdef LWM2M_RAW_BLOCK1_REQUESTS
lwm2m_raw_block1_create_callback_t rawBlock1CreateFunc;
lwm2m_raw_block1_write_callback_t rawBlock1WriteFunc;
lwm2m_raw_block1_execute_callback_t rawBlock1ExecuteFunc;
#endif
lwm2m_delete_callback_t deleteFunc;
lwm2m_discover_callback_t discoverFunc;
void * userData;
};
/*
* LWM2M Servers
*
* Since LWM2M Server Object instances are not accessible to LWM2M servers,
* there is no need to store them as lwm2m_objects_t
*/
typedef enum
{
STATE_DEREGISTERED = 0, // not registered or bootstrap not started
STATE_REG_HOLD_OFF, // initial registration delay or delay between retries
STATE_REG_PENDING, // registration pending
STATE_REGISTERED, // successfully registered
STATE_REG_FAILED, // last registration failed
STATE_REG_UPDATE_PENDING, // registration update pending
STATE_REG_UPDATE_NEEDED, // registration update required
STATE_REG_FULL_UPDATE_NEEDED, // registration update with objects required
STATE_DEREG_PENDING, // deregistration pending
STATE_BS_HOLD_OFF, // bootstrap hold off time
STATE_BS_INITIATED, // bootstrap request sent
STATE_BS_PENDING, // bootstrap ongoing
STATE_BS_FINISHING, // bootstrap finish received
STATE_BS_FINISHED, // bootstrap done
STATE_BS_FAILING, // bootstrap error occurred
STATE_BS_FAILED, // bootstrap failed
} lwm2m_status_t;
typedef enum
{
VERSION_MISSING = 0, // Version number not in registration.
VERSION_UNRECOGNIZED, // Version number in registration not recognized.
VERSION_1_0, // LWM2M version 1.0
VERSION_1_1, // LWM2M version 1.1
} lwm2m_version_t;
#define BINDING_UNKNOWN 0x01
#define BINDING_U 0x02 // UDP
#define BINDING_T 0x04 // TCP
#define BINDING_S 0x08 // SMS
#define BINDING_N 0x10 // Non-IP
#define BINDING_Q 0x20 // queue mode
/* Legacy bindings */
#define BINDING_UQ (BINDING_U|BINDING_Q) // UDP queue mode
#define BINDING_SQ (BINDING_S|BINDING_Q) // SMS queue mode
#define BINDING_US (BINDING_U|BINDING_S) // UDP plus SMS
#define BINDING_UQS (BINDING_U|BINDING_Q|BINDING_S) // UDP queue mode plus SMS
typedef uint8_t lwm2m_binding_t;
/*
* LWM2M block data
*
* Temporary data needed to handle block1 request and block2 responses.
*/
typedef enum
{
BLOCK_1,
BLOCK_2,
} block_type_t;
typedef union _block_data_identifier_
{
char * uri; // resource string if block1
int32_t mid; // mid of the last request if block2 eg the mid for the expected block
} block_data_identifier_t;
typedef struct _lwm2m_block_data_ lwm2m_block_data_t;
struct _lwm2m_block_data_
{
struct _lwm2m_block_data_ * next;
block_type_t blockType;
block_data_identifier_t identifier;
uint8_t * blockBuffer; // data buffer
size_t blockBufferSize; // buffer size
uint32_t blockNum; // block num of the last message received
#ifdef LWM2M_RAW_BLOCK1_REQUESTS
uint16_t mid; // mid of the last message received
#endif
};
typedef struct _lwm2m_server_
{
struct _lwm2m_server_ * next; // matches lwm2m_list_t::next
uint16_t secObjInstID; // matches lwm2m_list_t::id
uint16_t shortID; // servers short ID, may be 0 for bootstrap server
time_t lifetime; // lifetime of the registration in sec or 0 if default value (86400 sec), also used as hold off time for bootstrap servers
time_t registration; // date of the last registration in sec or end of client hold off time for bootstrap servers or end of hold off time for registration holds.
lwm2m_binding_t binding; // client connection mode with this server
void * sessionH;
lwm2m_status_t status;
char * location;
bool dirty;
lwm2m_block_data_t * blockData; // list to handle temporary block data.
#ifndef LWM2M_VERSION_1_0
uint16_t servObjInstID;// Server object instance ID if not a bootstrap server.
uint8_t attempt; // Current registration attempt
uint8_t sequence; // Current registration sequence
#endif
} lwm2m_server_t;
typedef struct _block_info_t
{
int block_num;
int block_size;
bool block_more;
} block_info_t;
/*
* LWM2M result callback
*
* When used with an observe, if 'data' is not nil, 'status' holds the observe counter.
*/
typedef void (*lwm2m_result_callback_t)(lwm2m_context_t *contextP, uint16_t clientID, lwm2m_uri_t *uriP, int status,
block_info_t *block_info, lwm2m_media_type_t format, uint8_t *data,
size_t dataLength, void *userData);
/*
* LWM2M Observations
*
* Used to store latest user operation on the observation of remote clients resources.
* Any node in the observation list means observation was established with client already.
* status STATE_REG_PENDING means the observe request was sent to the client but not yet answered.
* status STATE_REGISTERED means the client acknowledged the observe request.
* status STATE_DEREG_PENDING means the user canceled the request before the client answered it.
*/
typedef struct _lwm2m_observation_
{
struct _lwm2m_observation_ * next; // matches lwm2m_list_t::next
uint16_t id; // matches lwm2m_list_t::id
struct _lwm2m_client_ * clientP;
lwm2m_uri_t uri;
lwm2m_status_t status; // latest user operation
lwm2m_result_callback_t callback;
void * userData;
} lwm2m_observation_t;
/*
* LWM2M Link Attributes
*
* Used for observation parameters.
*
*/
#define LWM2M_ATTR_FLAG_MIN_PERIOD (uint8_t)0x01
#define LWM2M_ATTR_FLAG_MAX_PERIOD (uint8_t)0x02
#define LWM2M_ATTR_FLAG_GREATER_THAN (uint8_t)0x04
#define LWM2M_ATTR_FLAG_LESS_THAN (uint8_t)0x08
#define LWM2M_ATTR_FLAG_STEP (uint8_t)0x10
typedef struct
{
uint8_t toSet;
uint8_t toClear;
uint32_t minPeriod;
uint32_t maxPeriod;
double greaterThan;
double lessThan;
double step;
} lwm2m_attributes_t;
/*
* LWM2M Clients
*
* Be careful not to mix lwm2m_client_object_t used to store list of objects of remote clients
* and lwm2m_object_t describing objects exposed to remote servers.
*
*/
typedef struct _lwm2m_client_object_
{
struct _lwm2m_client_object_ * next; // matches lwm2m_list_t::next
uint16_t id; // matches lwm2m_list_t::id
uint8_t versionMajor;
uint8_t versionMinor;
lwm2m_list_t * instanceList;
} lwm2m_client_object_t;
typedef struct _lwm2m_client_
{
struct _lwm2m_client_ * next; // matches lwm2m_list_t::next
uint16_t internalID; // matches lwm2m_list_t::id
char * name;
lwm2m_version_t version;
lwm2m_binding_t binding;
char * msisdn;
char * altPath;
lwm2m_media_type_t format;
uint32_t lifetime;
time_t endOfLife;
void * sessionH;
lwm2m_client_object_t * objectList;
lwm2m_observation_t * observationList;
uint16_t observationId;
lwm2m_block_data_t * blockData; // list to handle temporary block data.
} lwm2m_client_t;
/*
* LWM2M transaction
*
* Adaptation of Erbium's coap_transaction_t
*/
typedef struct _lwm2m_transaction_ lwm2m_transaction_t;
typedef void (*lwm2m_transaction_callback_t) (lwm2m_context_t * contextP, lwm2m_transaction_t * transacP, void * message);
struct _lwm2m_transaction_
{
lwm2m_transaction_t * next; // matches lwm2m_list_t::next
uint16_t mID; // matches lwm2m_list_t::id
void * peerH;
uint8_t ack_received; // indicates, that the ACK was received
time_t response_timeout; // timeout to wait for response, if token is used. When 0, use calculated acknowledge timeout.
uint8_t retrans_counter;
time_t retrans_time;
void * message;
uint16_t buffer_len;
uint8_t * buffer;
size_t
payload_len; // the length of the entire payload, message payload might be smaller in case of a block1 transfer
uint8_t *payload; // carries the entire payload across multiple transactions in case of a block 1 transfer
lwm2m_transaction_callback_t callback;
void * userData;
};
/*
* LWM2M observed resources
*/
typedef struct _lwm2m_watcher_
{
struct _lwm2m_watcher_ * next;
bool active;
bool update;
lwm2m_server_t * server;
lwm2m_attributes_t * parameters;
lwm2m_media_type_t format;
uint8_t token[8];
size_t tokenLen;
time_t lastTime;
uint32_t counter;
uint16_t lastMid;
union
{
int64_t asInteger;
uint64_t asUnsigned;
double asFloat;
} lastValue;
} lwm2m_watcher_t;
typedef struct _lwm2m_observed_
{
struct _lwm2m_observed_ * next;
lwm2m_uri_t uri;
lwm2m_watcher_t * watcherList;
} lwm2m_observed_t;
#ifdef LWM2M_CLIENT_MODE
typedef enum
{
STATE_INITIAL = 0,
STATE_BOOTSTRAP_REQUIRED,
STATE_BOOTSTRAPPING,
STATE_REGISTER_REQUIRED,
STATE_REGISTERING,
STATE_READY
} lwm2m_client_state_t;
#endif
/*
* LWM2M Context
*/
#ifdef LWM2M_BOOTSTRAP_SERVER_MODE
// In all the following APIs, the session handle MUST uniquely identify a peer.
// LWM2M bootstrap callback
// When a LWM2M client requests bootstrap information, the callback is called with status COAP_NO_ERROR, uriP is nil and
// name is set. The callback must return a COAP_* error code. COAP_204_CHANGED for success.
// After a lwm2m_bootstrap_delete() or a lwm2m_bootstrap_write(), the callback is called with the status returned by the
// client, the URI of the operation (may be nil) and name is nil. The callback return value is ignored.
// If data is present and no preferred format is provided by the client the format will be 0, otherwise it will be set.
typedef int (*lwm2m_bootstrap_callback_t)(lwm2m_context_t *contextP, void *sessionH, uint8_t status, lwm2m_uri_t *uriP,
char *name, lwm2m_media_type_t format, uint8_t *data, size_t dataLength,
void *userData);
#endif
struct _lwm2m_context_
{
#ifdef LWM2M_CLIENT_MODE
lwm2m_client_state_t state;
char * endpointName;
char * msisdn;
char * altPath;
lwm2m_server_t * bootstrapServerList;
lwm2m_server_t * serverList;
lwm2m_object_t * objectList;
lwm2m_observed_t * observedList;
#endif
#if defined(LWM2M_SERVER_MODE) || defined(LWM2M_BOOTSTRAP_SERVER_MODE)
lwm2m_client_t * clientList;
#endif
#ifdef LWM2M_SERVER_MODE
lwm2m_result_callback_t monitorCallback;
void * monitorUserData;
#endif
#ifdef LWM2M_BOOTSTRAP_SERVER_MODE
lwm2m_bootstrap_callback_t bootstrapCallback;
void * bootstrapUserData;
#endif
uint16_t nextMID;
lwm2m_transaction_t * transactionList;
void * userData;
};
// initialize a liblwm2m context.
lwm2m_context_t * lwm2m_init(void * userData);
// close a liblwm2m context.
void lwm2m_close(lwm2m_context_t * contextP);
// perform any required pending operation and adjust timeoutP to the maximal time interval to wait in seconds.
int lwm2m_step(lwm2m_context_t * contextP, time_t * timeoutP);
// dispatch received data to liblwm2m
void lwm2m_handle_packet(lwm2m_context_t *contextP, uint8_t *buffer, size_t length, void *fromSessionH);
#ifdef LWM2M_CLIENT_MODE
// configure the client side with the Endpoint Name, binding, MSISDN (can be nil), alternative path
// for objects (can be nil) and a list of objects.
// LWM2M Security Object (ID 0) must be present with either a bootstrap server or a LWM2M server and
// its matching LWM2M Server Object (ID 1) instance
int lwm2m_configure(lwm2m_context_t * contextP, const char * endpointName, const char * msisdn, const char * altPath, uint16_t numObject, lwm2m_object_t * objectList[]);
int lwm2m_add_object(lwm2m_context_t * contextP, lwm2m_object_t * objectP);
int lwm2m_remove_object(lwm2m_context_t * contextP, uint16_t id);
// send a registration update to the server specified by the server short identifier
// or all if the ID is 0.
// If withObjects is true, the registration update contains the object list.
int lwm2m_update_registration(lwm2m_context_t * contextP, uint16_t shortServerID, bool withObjects);
// send deregistration to all servers connected to client
void lwm2m_deregister(lwm2m_context_t * context);
void lwm2m_resource_value_changed(lwm2m_context_t * contextP, lwm2m_uri_t * uriP);
#endif
#ifdef LWM2M_SERVER_MODE
// Clients registration/deregistration monitoring API.
// When a LWM2M client registers, the callback is called with status COAP_201_CREATED.
// When a LWM2M client deregisters, the callback is called with status COAP_202_DELETED.
// clientID is the internal ID of the LWM2M Client.
// The callback's parameters uri, data, dataLength are always NULL.
// The lwm2m_client_t is present in the lwm2m_context_t's clientList when the callback is called. On a deregistration, it deleted when the callback returns.
void lwm2m_set_monitoring_callback(lwm2m_context_t * contextP, lwm2m_result_callback_t callback, void * userData);
// Device Management APIs
int lwm2m_dm_read(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_result_callback_t callback, void * userData);
int lwm2m_dm_discover(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_result_callback_t callback, void * userData);
int lwm2m_dm_write(lwm2m_context_t *contextP, uint16_t clientID, lwm2m_uri_t *uriP, lwm2m_media_type_t format,
uint8_t *buffer, size_t length, bool partialUpdate, lwm2m_result_callback_t callback,
void *userData);
int lwm2m_dm_write_attributes(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_attributes_t * attrP, lwm2m_result_callback_t callback, void * userData);
int lwm2m_dm_execute(lwm2m_context_t *contextP, uint16_t clientID, lwm2m_uri_t *uriP, lwm2m_media_type_t format,
uint8_t *buffer, size_t length, lwm2m_result_callback_t callback, void *userData);
int lwm2m_dm_create(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, int numData, lwm2m_data_t * dataP, lwm2m_result_callback_t callback, void * userData);
int lwm2m_dm_delete(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_result_callback_t callback, void * userData);
// Information Reporting APIs
int lwm2m_observe(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_result_callback_t callback, void * userData);
int lwm2m_observe_cancel(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_result_callback_t callback, void * userData);
#endif
#ifdef LWM2M_BOOTSTRAP_SERVER_MODE
// Clients bootstrap request monitoring API.
// When a LWM2M client sends a bootstrap request, the callback is called with the client's endpoint name.
void lwm2m_set_bootstrap_callback(lwm2m_context_t * contextP, lwm2m_bootstrap_callback_t callback, void * userData);
// Boostrap Interface APIs
// if uriP is nil, a "Delete /" is sent to the client
int lwm2m_bootstrap_delete(lwm2m_context_t * contextP, void * sessionH, lwm2m_uri_t * uriP);
int lwm2m_bootstrap_write(lwm2m_context_t * contextP, void * sessionH, lwm2m_uri_t * uriP, lwm2m_media_type_t format, uint8_t * buffer, size_t length);
int lwm2m_bootstrap_finish(lwm2m_context_t * contextP, void * sessionH);
int lwm2m_bootstrap_discover(lwm2m_context_t * contextP, void * sessionH, lwm2m_uri_t * uriP);
#ifndef LWM2M_VERSION_1_0
int lwm2m_bootstrap_read(lwm2m_context_t * contextP, void * sessionH, lwm2m_uri_t * uriP);
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif