-
Notifications
You must be signed in to change notification settings - Fork 68
/
core.h
2044 lines (1922 loc) · 84 KB
/
core.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
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Copyright 2017-2024 AVSystem <avsystem@avsystem.com>
* AVSystem Anjay LwM2M SDK
* All rights reserved.
*
* Licensed under the AVSystem-5-clause License.
* See the attached LICENSE file for details.
*/
#ifndef ANJAY_INCLUDE_ANJAY_CORE_H
#define ANJAY_INCLUDE_ANJAY_CORE_H
#include <stdint.h>
#include <avsystem/coap/udp.h>
#include <avsystem/commons/avs_list.h>
#include <avsystem/commons/avs_net.h>
#include <avsystem/commons/avs_prng.h>
#include <avsystem/commons/avs_sched.h>
#include <avsystem/commons/avs_stream.h>
#include <avsystem/commons/avs_time.h>
#include <anjay/anjay_config.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Short Server ID type. */
typedef uint16_t anjay_ssid_t;
/** A constant that may be used in @ref anjay_schedule_registration_update
* call instead of Short Server ID to send Update messages to all connected
* servers. */
#define ANJAY_SSID_ANY 0
/** An SSID value reserved by LwM2M to refer to the Bootstrap Server.
* NOTE: The value of a "Short Server ID" Resource in the Security Object
* Instance referring to the Bootstrap Server is irrelevant and cannot be used
* to identify the Bootstrap Server. */
#define ANJAY_SSID_BOOTSTRAP UINT16_MAX
/** Anjay object containing all information required for LwM2M communication. */
typedef struct anjay_struct anjay_t;
/**
* Default transmission params recommended by the CoAP specification (RFC 7252).
*/
// clang-format off
#define ANJAY_COAP_DEFAULT_UDP_TX_PARAMS \
{ \
/* .ack_timeout = */ { 2, 0 }, \
/* .ack_random_factor = */ 1.5, \
/* .max_retransmit = */ 4, \
/* .nstart = */ 1 \
}
// clang-format on
/**
* Default handshake retransmission params recommended by the DTLS specification
* (RFC 6347), i.e: 1s for the initial response, growing exponentially (with
* each retransmission) up to maximum of 60s.
*/
// clang-format off
#define ANJAY_DTLS_DEFAULT_UDP_HS_TX_PARAMS \
{ \
/* .min = */ { 1, 0 }, \
/* .max = */ { 60, 0 } \
}
// clang-format on
#ifdef ANJAY_WITH_LWM2M11
typedef enum {
/**
* Lightweight Machine to Machine Technical Specification, Approved Version
* 1.0.2 - 2018-02-09 (OMA-TS-LightweightM2M-V1_0_2-20180209-A).
*/
ANJAY_LWM2M_VERSION_1_0,
/**
* Lightweight Machine to Machine Technical Specification, Approved Version
* 1.1.1 - 2019-06-17; Core (OMA-TS-LightweightM2M_Core-V1_1_1-20190617-A)
* and Transport Bindings
* (OMA-TS-LightweightM2M_Transport-V1_1_1-20190617-A).
*/
ANJAY_LWM2M_VERSION_1_1
} anjay_lwm2m_version_t;
typedef struct {
/**
* The lowest version to attempt using when registering to LwM2M Servers.
*/
anjay_lwm2m_version_t minimum_version;
/**
* The highest version to attempt using when registering to LwM2M Servers.
* This is also the version number sent in reponse to Bootstrap Discover.
*/
anjay_lwm2m_version_t maximum_version;
} anjay_lwm2m_version_config_t;
#endif // ANJAY_WITH_LWM2M11
#ifdef ANJAY_WITH_CONN_STATUS_API
/**
* @experimental This is experimental server connection status API. This API can
* change in future versions without any notice.
*
* This enum represents the possible states of a server connection.
*/
typedef enum anjay_server_conn_status {
/**
* Invalid state. It is only returned if a given server connection object
* does not exist, or there was an error in determining its state.
*/
ANJAY_SERV_CONN_STATUS_INVALID,
/**
* Generic state for any errors for which more specific states are not
* defined. For a regular LwM2M Server, this means that the primary
* connection is invalid or de-register/update operation has failed. For a
* LwM2M Bootstrap Server, it means that the bootstrap process failed.
*/
ANJAY_SERV_CONN_STATUS_ERROR,
/**
* This status means that the server connection object has been just created
* as a result of the Security and Server object instances having been
* previously added to the data model. A connection attempt is scheduled to
* be made during subsequent calls to @ref anjay_sched_run.
*/
ANJAY_SERV_CONN_STATUS_INITIAL,
/**
* This status is reported just before attempting the connection procedure,
* which may include binding the socket to a local port, performing DNS
* resolution, connecting the socket, and performing a (D)TLS handshake.
*/
ANJAY_SERV_CONN_STATUS_CONNECTING,
/**
* This status means that the bootstrap process is in progress. It only
* applies to LwM2M Bootstrap Servers.
*/
ANJAY_SERV_CONN_STATUS_BOOTSTRAPPING,
/**
* This status means that the bootstrap process has completed successfully.
* It only applies to LwM2M Bootstrap Servers.
*/
ANJAY_SERV_CONN_STATUS_BOOTSTRAPPED,
/**
* This status means that the register operation is in progress. It only
* applies to regular LwM2M Servers.
*/
ANJAY_SERV_CONN_STATUS_REGISTERING,
/**
* This status means that the Anjay is registered to the LwM2M Server. It
* only applies to regular LwM2M Servers.
*/
ANJAY_SERV_CONN_STATUS_REGISTERED,
/**
* This status means that the last register operation has failed due to no
* response, a non-success CoAP response was received, or network problems.
* It only applies to regular LwM2M Servers.
*/
ANJAY_SERV_CONN_STATUS_REG_FAILURE,
/**
* This status means that the de-register operation is in progress. It
* only applies to regular LwM2M Servers.
*/
ANJAY_SERV_CONN_STATUS_DEREGISTERING,
/**
* This status means that the the library has de-registered with the LwM2M
* Server, either explicitly by successfully performing the De-register
* operation, or implicitly by discarding the registration state (which
* happens when the server is disabled while offline). It only applies to
* regular LwM2M Servers.
*/
ANJAY_SERV_CONN_STATUS_DEREGISTERED,
/**
* This status means that the /1/x/4 resource has been executed and Anjay
* will try to suspend the LwM2M Server. It only applies to regular LwM2M
* Servers.
*/
ANJAY_SERV_CONN_STATUS_SUSPENDING,
/**
* This status means that the suspend process has completed successfully. It
* only applies to regular LwM2M Servers.
*/
ANJAY_SERV_CONN_STATUS_SUSPENDED,
/**
* This status means that the last update operation has failed due to either
* no response or a non-success CoAP response was received. It only
* applies to regular LwM2M Servers.
*/
ANJAY_SERV_CONN_STATUS_REREGISTERING,
/**
* This status means that the update operation is in progress. It only
* applies to regular LwM2M Servers.
*/
ANJAY_SERV_CONN_STATUS_UPDATING
} anjay_server_conn_status_t;
/**
* @experimental This is experimental server connection status API. This API can
* change in future versions without any notice.
*
* Callback called each time there is a transition of a server connection status
* (as listed in @ref anjay_server_conn_status_t ).
*
* @param arg Opaque argument as set through the @c
* server_connection_status_cb_arg field in @ref
* anjay_configuration_t
*
* @param anjay Anjay object that calls this callback
*
* @param ssid Short Server ID of the server for which the status is reported
*
* @param status New status of the server connection
*/
typedef void
anjay_server_connection_status_cb_t(void *arg,
anjay_t *anjay,
anjay_ssid_t ssid,
anjay_server_conn_status_t status);
/**
* @experimental This is experimental server connection status API. This API can
* change in future versions without any notice.
*
* This function returns the server connection status. Possible statuses are
* given in the @ref anjay_server_conn_status_t. Statuses for a LwM2M Bootstrap
* Server are different from the statuses for a regular LwM2M Server.
*
* @param anjay Anjay object to operate on.
* @param ssid Short Server ID of the server which status will be returned. @ref
* ANJAY_SSID_ANY is not a valid argument.
*
* @returns Server status on success, in case of error
* ANJAY_SERV_CONN_STATUS_UNKNOWN.
*/
anjay_server_conn_status_t
anjay_get_server_connection_status(anjay_t *anjay, anjay_ssid_t ssid);
#endif // ANJAY_WITH_CONN_STATUS_API
typedef struct anjay_configuration {
/**
* Endpoint name as presented to the LwM2M server. Must be non-NULL, or
* otherwise @ref anjay_new() will fail.
*
* NOTE: Endpoint name is copied during @ref anjay_new() and cannot be
* modified later on.
*/
const char *endpoint_name;
/**
* UDP port number that all listening sockets will be bound to. It may be
* left at 0 - in that case, connection with each server will use a freshly
* generated ephemeral port number.
*/
uint16_t udp_listen_port;
/**
* DTLS version to use for communication.
*/
avs_net_ssl_version_t dtls_version;
/**
* Maximum size of a single incoming CoAP message. Decreasing this value
* reduces memory usage, but packets bigger than this value will
* be dropped.
*/
size_t in_buffer_size;
/**
* Maximum size of a single outgoing CoAP message. If the message exceeds
* this size, the library performs the block-wise CoAP transfer
* ( https://tools.ietf.org/html/rfc7959 ).
* NOTE: in case of block-wise transfers, this value limits the payload size
* for a single block, not the size of a whole packet.
*/
size_t out_buffer_size;
/**
* Number of bytes reserved for caching CoAP responses. If not 0,
* the library looks up recently generated responses and reuses them
* to handle retransmitted packets (ones with identical CoAP message ID).
*
* NOTE: while a single cache is used for all LwM2M servers, cached
* responses are tied to a particular server and not reused for other ones.
*/
size_t msg_cache_size;
/**
* Socket configuration to use when creating TCP/UDP sockets.
*
* Note that:
* - <c>reuse_addr</c> will be forced to true.
* - Value pointed to by the <c>preferred_endpoint</c> will be ignored.
*/
avs_net_socket_configuration_t socket_config;
/**
* Configuration of the CoAP transmission params for UDP connection, as per
* RFC 7252.
*
* If NULL, the default configuration @ref ANJAY_COAP_DEFAULT_UDP_TX_PARAMS
* will be selected.
*
* NOTE: Parameters are copied during @ref anjay_new() and cannot be
* modified later on.
*/
const avs_coap_udp_tx_params_t *udp_tx_params;
/**
* Configuration of the DTLS handshake retransmission timeouts for UDP
* connection.
*
* If NULL, the default configuration
* @ref ANJAY_DTLS_DEFAULT_UDP_HS_TX_PARAMS will be selected.
*
* NOTE: Parameters are copied during @ref anjay_new() and cannot be
* modified later on.
*
* IMPORTANT: In case of a need to adjust DTLS retransmission params to
* match the CoAP retransmission params, the @ref udp_dtls_hs_tx_params
* shall be initialized as `dtls_hs_params` is in the following code
* snippet:
* @code
* const avs_coap_udp_tx_params_t coap_tx_params = {
* // ... some initialization
* };
*
* // Without ACK_RANDOM_FACTOR = 1.0, it is impossible to create a DTLS HS
* // configuration that matches CoAP retransmission configuration
* // perfectly.
* assert(coap_tx_params.ack_random_factor == 1.0);
*
* const avs_net_dtls_handshake_timeouts_t dtls_hs_tx_params = {
* .min = avs_time_duration_fmul(coap_tx_params.ack_timeout,
* coap_tx_params.ack_random_factor),
* .max = avs_time_duration_fmul(
* coap_tx_params.ack_timeout,
* (1 << coap_tx_params.max_retransmit)
* * coap_tx_params.ack_random_factor)
* };
* @endcode
*/
const avs_net_dtls_handshake_timeouts_t *udp_dtls_hs_tx_params;
/**
* Controls whether Notify operations are conveyed using Confirmable CoAP
* messages by default.
*/
bool confirmable_notifications;
/**
* If set to true, connection to the Bootstrap Server will be closed
* immediately after making a successful connection to any regular LwM2M
* Server and only opened again if (re)connection to a regular server is
* rejected.
*
* If set to false, legacy Server-Initiated Bootstrap is possible, i.e. the
* Bootstrap Server can reach the client at any time to re-initiate the
* bootstrap sequence.
*
* NOTE: This parameter controls a legacy Server-Initiated Bootstrap
* mechanism based on an interpretation of LwM2M 1.0 TS that is not
* universally accepted. Server-Initiated Bootstrap as specified in LwM2M
* 1.1 TS is always supported, regardless of this setting.
*/
bool disable_legacy_server_initiated_bootstrap;
/**
* If "Notification Storing When Disabled or Offline" resource is set to
* true and either the client is in offline mode, or uses Queue Mode,
* Notify messages are enqueued and sent whenever the client is online
* again. This value allows one to limit the size of said notification
* queue. The limit applies to notifications queued for all servers.
*
* If set to 0, size of the stored notification queue is only limited by
* the amount of available RAM.
*
* If set to a positive value, that much *most recent* notifications are
* stored. Attempting to add a notification to the queue while it is
* already full drops the oldest one to make room for new one.
*/
size_t stored_notification_limit;
/**
* Sets the preference of the library for Content-Format used when
* responding to a request without Accept option.
*
* If set to true, the formats used would be:
* - for LwM2M 1.0: TLV,
* - for LwM2M 1.1: SenML CBOR, or if not compiled in, SenML JSON, or if
* not compiled in TLV.
*/
bool prefer_hierarchical_formats;
/**
* Enables support for DTLS connection_id extension for all DTLS
* connections.
*/
bool use_connection_id;
/**
* Send the Update message immediately when Object Instances are created or
* deleted.
*
* NOTE: In case of Create and Delete operations, the Update message will be
* immediately sent to <strong>all</strong> the servers, including the one
* that initiated the operation.
*
* By default, such data model changes are reported in the next scheduled
* update message (or the message can be requested using
* @ref anjay_schedule_registration_update), but the Update is not triggered
* automatically.
*/
bool update_immediately_on_dm_change;
/**
* Send the Notify messages as a result of a server action (e.g. Write) even
* to the initiating server.
*
* By default, notifications resulting from server actions are only sent to
* the servers other than the one which initiated the action.
*/
bool enable_self_notify;
/**
* Treat failures of the "connect" socket operation (e.g. (D)TLS handshake
* failures) as a failed LwM2M Register operation. This enables automatic
* retrying of them as described in the "Bootstrap and LwM2M Server
* Registration Mechanisms" of LwM2M Core TS 1.1.
*
* When disabled, such failures are treated as fatal errors and cause the
* entire registration sequence for that server to be aborted (which will
* trigger a fallback to Bootstrap if applicable).
*/
bool connection_error_is_registration_failure;
/**
* (D)TLS ciphersuites to use if the "DTLS/TLS Ciphersuite" Resource
* (/0/x/16) is not available or empty.
*
* Passing a value with <c>num_ids == 0</c> (default) will cause defaults of
* the TLS backend library to be used.
*
* Contents of the <c>ids</c> array are copied, so it is safe to free the
* passed array after the call to @ref anjay_new.
*/
avs_net_socket_tls_ciphersuites_t default_tls_ciphersuites;
/**
* Custom PRNG context to use. If @c NULL , a default one is used, with
* entropy source specific to selected cryptograpic backend. If default
* entropy source isn't available, creation of Anjay object will fail.
*
* Used for establishing TLS and DTLS connections, generation of tokens and
* by OSCORE module, if it's available.
*
* If not @c NULL , then MUST outlive created Anjay object.
*/
avs_crypto_prng_ctx_t *prng_ctx;
/**
* Callback that will be executed when initializing TLS and DTLS
* connections, that can be used for additional configuration of the TLS
* backend.
*/
avs_ssl_additional_configuration_clb_t *additional_tls_config_clb;
#if defined(WITH_AVS_COAP_TCP) \
&& (defined(ANJAY_WITH_LWM2M11) || defined(ANJAY_WITH_COAP_DOWNLOAD))
/**
* Maximum expected TCP options size. CoAP messages with options longer
* than this value will be rejected.
*
* If set to 0, a hard-coded default value (128) will be used.
*/
size_t coap_tcp_max_options_size;
/**
* Time to wait for incoming response after sending a request. After this
* time request is considered unsuccessful.
*
* If zero-initialized or set to @c AVS_TIME_DURATION_ZERO, a default
* value of 30s is used.
*/
avs_time_duration_t coap_tcp_request_timeout;
#endif // defined(WITH_AVS_COAP_TCP) && (defined(ANJAY_WITH_LWM2M11) ||
// defined(ANJAY_WITH_COAP_DOWNLOAD))
#ifdef ANJAY_WITH_LWM2M11
/**
* Configuration of LwM2M protocol versions to use when attempting to
* register to LwM2M servers.
*
* If NULL, the default configuration, that allows all supported versions to
* be used, will be selected.
*
* Notes:
* - Configuration is copied during @ref anjay_new() and cannot be
* modified later on.
* - Restricting the set of supported versions may speed up the Register
* operation, as less versions will be attempted for registration.
* - If <c>minimum_version</c> is set to a higher value than
* <c>maximum_version</c>, @ref anjay_new will fail.
* - If <c>minimum_version</c> is set to a version higher than LwM2M 1.0,
* <c>disable_legacy_server_initiated_bootstrap</c> will be effectively
* implied even if that field is set to <c>false</c>.
*/
const anjay_lwm2m_version_config_t *lwm2m_version_config;
/**
* Enable usage of system-wide trust store (e.g. <c>/etc/ssl/certs</c> on
* most Unix-like systems) for PKIX certificate verification in addition to
* those specified via <c>trust_store_certs</c> and <c>trust_store_crls</c>.
*
* NOTE: System-wide trust store is currently supported only by the OpenSSL
* backend. This field will not have the intended effect with the Mbed TLS
* backend.
*
* NOTE: PKIX certificate verification is only used in certain "Certificate
* Usage" modes configured in the Security object of the data model. It is
* also not automatically propagated to downloads, although is passed
* through by @ref anjay_security_config_from_dm.
*
* NOTE: System-wide trust store will be disabled for connections using the
* trust store updated through the <c>/est/crts</c> request, regardless of
* the value of this flag.
*/
bool use_system_trust_store;
/**
* Store of trust anchor certificates to use for PKIX certificate
* verification. This field is optional and can be left zero-initialized. If
* used, it shall be initialized using one of the
* <c>avs_crypto_trusted_cert_info_from_*</c> helper functions.
*
* Any data passed is copied immediately, so it is safe to free any
* associated buffers after calling @ref anjay_new.
*
* NOTE: PKIX certificate verification is only used in certain "Certificate
* Usage" modes configured in the Security object of the data model. It is
* also not automatically propagated to downloads, although is passed
* through by @ref anjay_security_config_from_dm.
*/
avs_crypto_certificate_chain_info_t trust_store_certs;
/**
* Store of certificate revocation lists to use for PKIX certificate
* verification. This field is optional and can be left zero-initialized. If
* used, it shall be initialized using one of the
* <c>avs_crypto_cert_revocation_list_info_from_*</c> helper functions.
*
* Any data passed is copied immediately, so it is safe to free any
* associated buffers after calling @ref anjay_new.
*
* NOTE: PKIX certificate verification is only used in certain "Certificate
* Usage" modes configured in the Security object of the data model. It is
* also not automatically propagated to downloads, although is passed
* through by @ref anjay_security_config_from_dm.
*/
avs_crypto_cert_revocation_list_info_t trust_store_crls;
/**
* Enable rebuilding of client certificate chain based on certificates in
* the trust store.
*
* If this field is set to <c>true</c>, when performing a (D)TLS handshake,
* if the client certificate configured in the data model (or the last
* certificate in a chain) is not self-signed, Anjay will attempt to find
* its ancestors in the appropriate trust store (which may be
* <c>trust_store_certs</c> or the one provisioned by <c>/est/crts</c>
* operation) and append them to the chain presented during handshake.
*/
bool rebuild_client_cert_chain;
#endif // ANJAY_WITH_LWM2M11
#ifdef ANJAY_WITH_CONN_STATUS_API
/**
* @experimental This is experimental server connection status API. This API
* can change in future versions without any notice.
*
* Function called each time there is a transition of a server connection
* status (as listed in @ref anjay_server_conn_status_t ).
*/
anjay_server_connection_status_cb_t *server_connection_status_cb;
/**
* @experimental This is experimental server connection status API. This API
* can change in future versions without any notice.
*
* Opaque argument that will be passed to the function configured in the
* <c>server_connection_status_cb</c> field.
*
* If <c>server_connection_status_cb</c> is NULL, this field is ignored.
*/
void *server_connection_status_cb_arg;
#endif // ANJAY_WITH_CONN_STATUS_API
} anjay_configuration_t;
/**
* @returns pointer to the string representing current version of the library.
*/
const char *anjay_get_version(void);
/**
* Creates a new Anjay object.
*
* @param config Initial configuration. For details, see
* @ref anjay_configuration_t .
*
* @returns Created Anjay object on success, NULL in case of error.
*/
anjay_t *anjay_new(const anjay_configuration_t *config);
/**
* Cleans up all resources and releases the Anjay object.
*
* <strong>NOTE:</strong> It shall be called <strong>before</strong> freeing
* LwM2M Objects registered within the <c>anjay</c> object.
*
* <strong>NOTE:</strong> The <c>anjay</c> pointer is invalidated during the
* call to this function. If Anjay is compiled with thread safety enabled, all
* the intermediary cleanup code is properly synchronized, but you should still
* make sure that no other thread is able to access the <c>anjay</c> object
* before calling this function, to avoid its usage after <em>free</em>.
*
* @param anjay Anjay object to delete. MUST NOT be @c NULL .
*/
void anjay_delete(anjay_t *anjay);
/**
* Retrieves a list of sockets used for communication with LwM2M servers.
* Returned list must not be freed nor modified.
*
* Example usage: poll()-based application loop
*
* @code
* struct pollfd poll_fd = { .events = POLLIN, .fd = -1 };
*
* while (true) {
* AVS_LIST(avs_net_socket_t*) sockets = anjay_get_sockets(anjay);
* if (sockets) {
* // assuming there is only one socket
* poll_fd.fd = *(const int*)avs_net_socket_get_system(*sockets);
* } else {
* // sockets not initialized yet
* poll_fd.fd = -1;
* }
* if (poll(&poll_fd, 1, 1000) > 0) {
* if (poll_fd.revents & POLLIN) {
* if (anjay_serve(anjay, *sockets)) {
* log("anjay_serve failed");
* }
* }
* }
* }
* @endcode
*
* <strong>NOTE:</strong> The returned list will be invalidated by any
* subsequent call to <c>anjay_get_sockets()</c> or
* @ref anjay_get_socket_entries . If you need to call these functions from
* multiple threads, you need to implement additional synchronization to achieve
* thread safety.
*
* The socket object pointers themselves may additionally be invalidated by a
* call to @ref anjay_sched_run, @ref anjay_serve, @ref anjay_serve_any or
* during the execution of @ref anjay_event_loop_run or
* @ref anjay_event_loop_run_with_error_handling . For this reason, it is
* recommended to only call this function from callback functions called from
* within Anjay, in scheduler jobs, or as part of a custom event loop.
*
* @param anjay Anjay object to operate on.
*
* @returns A list of valid server sockets on success,
* NULL when the device is not connected to any server.
*/
AVS_LIST(avs_net_socket_t *const) anjay_get_sockets(anjay_t *anjay);
typedef enum {
ANJAY_SOCKET_TRANSPORT_INVALID = -1,
ANJAY_SOCKET_TRANSPORT_UDP = 0,
ANJAY_SOCKET_TRANSPORT_TCP,
ANJAY_SOCKET_TRANSPORT_SMS,
ANJAY_SOCKET_TRANSPORT_NIDD
} anjay_socket_transport_t;
/**
* A structure that describes an open socket used by Anjay. Returned by
* @ref anjay_get_socket_entries.
*/
typedef struct {
/**
* The socket described by this structure. It is intended to be used
* directly only for checking whether there is data ready, using mechanisms
* such as <c>select()</c> or <c>poll()</c>.
*/
avs_net_socket_t *socket;
/**
* Transport layer used by <c>socket</c>.
*
* Guaranteed to not be @ref ANJAY_SOCKET_TRANSPORT_INVALID, that value is
* only used internally.
*/
anjay_socket_transport_t transport;
/**
* SSID of the server to which the socket is related. May be:
* - <c>ANJAY_SSID_ANY</c> if the socket is not directly and unambiguously
* related to any server, which includes:
* - download sockets
* - SMS communication socket (common for all servers; only in versions of
* Anjay that include the SMS commercial feature)
* - <c>ANJAY_SSID_BOOTSTRAP</c> for the Bootstrap Server socket
* - any other value for sockets related to regular LwM2M servers
*/
anjay_ssid_t ssid;
/**
* Flag that is true in the following cases:
* - it is a UDP communication socket for a regular LwM2M server that is
* configured to use the "queue mode", or
* - it is an SMS communication socket and all LwM2M servers that use this
* transport use the "queue mode" (only relevant to versions of Anjay that
* include the SMS commercial feature)
*
* In either case, a queue mode socket will stop being returned from
* @ref anjay_get_sockets and @ref anjay_get_socket_entries after period
* defined by CoAP <c>MAX_TRANSMIT_WAIT</c> since last communication.
*/
bool queue_mode;
} anjay_socket_entry_t;
/**
* Retrieves a list of structures that describe sockets used for communication
* with LwM2M servers. Returned list must not be freed nor modified.
*
* The returned data is equivalent to the one that can be retrieved using
* @ref anjay_get_sockets - but includes additional data that describes the
* socket in addition to the socket itself. See @ref anjay_socket_entry_t for
* details.
*
* <strong>NOTE:</strong> The returned list will be invalidated by any
* subsequent call to @ref anjay_get_sockets or <c>anjay_get_socket_entries</c>.
* If you need to call these functions from multiple threads, you need to
* implement additional synchronization to achieve thread safety.
*
* The socket object pointers themselves may additionally be invalidated by a
* call to @ref anjay_sched_run, @ref anjay_serve, @ref anjay_serve_any or
* during the execution of @ref anjay_event_loop_run or
* @ref anjay_event_loop_run_with_error_handling . For this reason, it is
* recommended to only call this function from callback functions called from
* within Anjay, in scheduler jobs, or as part of a custom event loop.
*
* @param anjay Anjay object to operate on.
*
* @returns A list of valid server socket entries on success,
* NULL when the device is not connected to any server.
*/
AVS_LIST(const anjay_socket_entry_t) anjay_get_socket_entries(anjay_t *anjay);
/**
* Reads a message from given @p ready_socket and handles it appropriately.
*
* Initially, the receive method on the underlying socket is called with receive
* timeout set to zero. Subsequent receive requests may block with non-zero
* timeout values when e.g. waiting for retransmissions or subsequent BLOCK
* chunks - this is necessary to hide this complexity from the user callbacks in
* streaming mode.
*
* This function may handle more than one request at once. Upon successful
* return, it is guaranteed that there is no more data to be received on the
* socket at the moment.
*
* @param anjay Anjay object to operate on.
* @param ready_socket A socket to read the message from.
*
* @returns 0 on success, a negative value in case of error. Note that it
* includes non-fatal errors, such as receiving a malformed packet.
*/
int anjay_serve(anjay_t *anjay, avs_net_socket_t *ready_socket);
/** Object ID */
typedef uint16_t anjay_oid_t;
/** Object Instance ID */
typedef uint16_t anjay_iid_t;
/** Resource ID */
typedef uint16_t anjay_rid_t;
/** Resource Instance ID */
typedef uint16_t anjay_riid_t;
/**
* Value reserved by the LwM2M spec for all kinds of IDs (Object IDs, Object
* Instance IDs, Resource IDs, Resource Instance IDs, Short Server IDs).
*/
#define ANJAY_ID_INVALID UINT16_MAX
/** Helper macro used to define ANJAY_ERR_ constants.
* Generated values are valid CoAP Status Codes encoded as a single byte. */
#define ANJAY_COAP_STATUS(Maj, Min) ((uint8_t) ((Maj << 5) | (Min & 0x1F)))
/** Error values that may be returned from data model handlers. @{ */
/**
* Request sent by the LwM2M Server was malformed or contained an invalid
* value.
*/
#define ANJAY_ERR_BAD_REQUEST (-(int) ANJAY_COAP_STATUS(4, 0))
/**
* LwM2M Server is not allowed to perform the operation due to lack of
* necessary access rights.
*/
#define ANJAY_ERR_UNAUTHORIZED (-(int) ANJAY_COAP_STATUS(4, 1))
/**
* Low-level CoAP error code; used internally by Anjay when CoAP option values
* were invalid.
*/
#define ANJAY_ERR_BAD_OPTION (-(int) ANJAY_COAP_STATUS(4, 2))
#define ANJAY_ERR_FORBIDDEN (-(int) ANJAY_COAP_STATUS(4, 3))
/** Target of the operation (Object/Instance/Resource) does not exist. */
#define ANJAY_ERR_NOT_FOUND (-(int) ANJAY_COAP_STATUS(4, 4))
/**
* Operation is not allowed in current device state or the attempted operation
* is invalid for this target (Object/Instance/Resource)
*/
#define ANJAY_ERR_METHOD_NOT_ALLOWED (-(int) ANJAY_COAP_STATUS(4, 5))
/**
* Low-level CoAP error code; used internally by Anjay when the client is
* unable to encode response in requested content format.
*/
#define ANJAY_ERR_NOT_ACCEPTABLE (-(int) ANJAY_COAP_STATUS(4, 6))
/**
* Low-level CoAP error code; used internally by Anjay in case of unrecoverable
* problems during block-wise transfer.
*/
#define ANJAY_ERR_REQUEST_ENTITY_INCOMPLETE (-(int) ANJAY_COAP_STATUS(4, 8))
/**
* The server requested operation has a Content Format option that is
* unsupported by Anjay.
*/
#define ANJAY_ERR_UNSUPPORTED_CONTENT_FORMAT (-(int) ANJAY_COAP_STATUS(4, 15))
/** Unspecified error, no other error code was suitable. */
#define ANJAY_ERR_INTERNAL (-(int) ANJAY_COAP_STATUS(5, 0))
/** Operation is not implemented by the LwM2M Client. */
#define ANJAY_ERR_NOT_IMPLEMENTED (-(int) ANJAY_COAP_STATUS(5, 1))
/**
* LwM2M Client is busy processing some other request; LwM2M Server may retry
* sending the same request after some delay.
*/
#define ANJAY_ERR_SERVICE_UNAVAILABLE (-(int) ANJAY_COAP_STATUS(5, 3))
/** @} */
/**
* Extracts the scheduler used by Anjay allowing the user to schedule his own
* tasks.
*
* See docs of [avs_commons library](https://github.com/AVSystem/avs_commons/
* blob/master/include_public/avsystem/commons/sched.h) for API of
* @c avs_sched_t object.
*
* **Must not** use @c avs_sched_cleanup on the returned scheduler. Anjay will
* cleanup it itself.
*
* @param anjay Anjay object to operate on.
*
* @returns non-null scheduler object used by Anjay.
*/
avs_sched_t *anjay_get_scheduler(anjay_t *anjay);
/**
* Determines time of next scheduled task.
*
* May be used to determine how long the device may wait before calling
* @ref anjay_sched_run .
*
* @param anjay Anjay object to operate on.
* @param[out] out_delay Relative time from now of next scheduled task.
*
* @returns 0 on success, or a negative value if no tasks are scheduled.
*/
int anjay_sched_time_to_next(anjay_t *anjay, avs_time_duration_t *out_delay);
/**
* Determines time of next scheduled task in milliseconds.
*
* This function is equivalent to @ref anjay_sched_time_to_next but, as a
* convenience for users of system calls such as <c>poll()</c>, the result is
* returned as a single integer number of milliseconds.
*
* @param anjay Anjay object to operate on.
* @param[out] out_delay_ms Relative time from now of next scheduled task, in
* milliseconds.
*
* @returns 0 on success, or a negative value if no tasks are scheduled.
*/
int anjay_sched_time_to_next_ms(anjay_t *anjay, int *out_delay_ms);
/**
* Calculates time in milliseconds the client code may wait for incoming events
* before the need to call @ref anjay_sched_run .
*
* This function combines @ref anjay_sched_time_to_next_ms with a user-provided
* limit, so that a conclusive value will always be returned. It is provided as
* a convenience for users of system calls such as <c>poll()</c>.
*
* @param anjay Anjay object to operate on.
* @param limit_ms The longest amount of time the function shall return.
*
* @returns Relative time from now of next scheduled task, in milliseconds, if
* such task exists and it's scheduled to run earlier than
* <c>limit_ms</c> seconds from now, or <c>limit_ms</c> otherwise.
*/
int anjay_sched_calculate_wait_time_ms(anjay_t *anjay, int limit_ms);
/**
* Runs all scheduled events which need to be invoked at or before the time of
* this function invocation.
*
* @param anjay Anjay object to operate on.
*/
void anjay_sched_run(anjay_t *anjay);
#ifdef ANJAY_WITH_EVENT_LOOP
/**
* Runs Anjay's main event loop that executes @ref anjay_serve and
* @ref anjay_sched_run as appropriate.
*
* This function will only return after either:
*
* - @ref anjay_event_loop_interrupt is called (from a different thread or from
* a user callback), or
* - a fatal error (e.g. out-of-memory) occurs in the loop itself (errors from
* @ref anjay_serve are <em>not</em> considered fatal)
*
* <strong>IMPORTANT:</strong> The preimplemented event loop is primarily
* intended to be run in a dedicated thread, while other threads may handle
* tasks not related to LwM2M. It is safe to control the same instance of Anjay
* concurrently from a different thread <strong>only if</strong> the thread
* safety features have been enabled at Anjay's compile time:
*
* - <c>AVS_COMMONS_SCHED_THREAD_SAFE</c> (<c>WITH_SCHEDULER_THREAD_SAFE</c> in
* CMake) is required to safely use Anjay's internal scheduler (see
* @ref anjay_get_scheduler)
* - Please note that only managing scheduler tasks from another thread is
* safe. Attempting to call @ref anjay_sched_run (or
* <c>avs_sched_run(anjay_get_scheduler(anjay))</c> while the event loop is
* running <strong>may lead to undefined behavior in the loop</strong>
* - <c>ANJAY_WITH_THREAD_SAFETY</c> (<c>WITH_THREAD_SAFETY</c> in CMake) is
* required to call any other functions, aside from the cleanup functions
* (which are only safe to call after the event loop has finished) and
* @ref anjay_event_loop_interrupt (which is always safe to call)
*
* <strong>CAUTION:</strong> The preimplemented event loop will only work if all
* the sockets that may be created by Anjay will return file descriptors
* compatible with <c>poll()</c> or <c>select()</c> through
* <c>avs_net_socket_get_system()</c>.
*
* In particular, please be cautious when using SMS or NIDD transports (in
* versions of Anjay that include the relevant commercial features) - your
* <c>anjay_smsdrv_system_socket_t</c> and
* <c>anjay_nidd_driver_system_descriptor_t</c> functions need to populate the
* output argument with a valid file descriptor (e.g.
* <c>int fd = ...; *out = &fd;</c>), and that file descriptor must be valid to
* use with the <c>poll()</c> or <c>select()</c> functions (which may not true
* if the socket API is separate from other IO APIs, as is the case e.g. on
* Windows). Otherwise attempting to use this event loop implementation will not
* handle NIDD and SMS transports properly, and may even lead to undefined
* behavior.
*
* @param anjay Anjay object to operate on.
* @param max_wait_time Maximum time to spend in each single call to
* <c>poll()</c> or <c>select()</c>. Larger times will
* prevent the event loop thread from waking up too
* frequently. However, during this wait time, the call to
* @ref anjay_event_loop_interrupt may not be handled
* immediately, and scheduler jobs requested from other
* threads (see @ref anjay_get_scheduler) will not be
* executed, so shortening this time will make the
* scheduler more responsive.
*
* @returns 0 after having been successfully interrupted by
* @ref anjay_event_loop_interrupt, or a negative value in case of a
* fatal error.
*/
int anjay_event_loop_run(anjay_t *anjay, avs_time_duration_t max_wait_time);
/**
* Act same as @ref anjay_event_loop_run, but when none of the configured
* servers could be reached, try to reconnect using function @ref
* anjay_transport_schedule_reconnect.
*
* @param anjay Anjay object to operate on.
* @param max_wait_time Maximum time to spend in each single call to
* <c>poll()</c> or <c>select()</c>. Larger times will
* prevent the event loop thread from waking up too
* frequently. However, during this wait time, the call to
* @ref anjay_event_loop_interrupt may not be handled
* immediately, and scheduler jobs requested from other